hd1000a.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * hd1000a.cpp : Roku HD1000 audio output
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: 78a77d1cba7e0d3ea85d5b06ad594884c0fe7ab0 $
  6.  *
  7.  * Author: Jon Lech Johansen <jon-vl@nanocrew.net>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. extern "C"
  27. {
  28. #include <errno.h>
  29. #ifdef HAVE_CONFIG_H
  30. # include "config.h"
  31. #endif
  32. #include <vlc_common.h>
  33. #include <vlc_plugin.h>
  34. #include <vlc_aout.h>
  35. #include "aout_internal.h"
  36. }
  37. #include <deschutes/libraries/hdmachinex225/PCMAudioPlayer.h>
  38. #define FRAME_SIZE 4096
  39. /*****************************************************************************
  40.  * aout_sys_t: audio output method descriptor
  41.  *****************************************************************************
  42.  * This structure is part of the audio output thread descriptor.
  43.  * It describes the direct sound specific properties of an audio device.
  44.  *****************************************************************************/
  45. struct aout_sys_t
  46. {
  47.     u32 nAlignment;
  48.     u32 nSizeMultiple;
  49.     u32 nBuffers;
  50.     u32 nBufferSize;
  51.     void ** ppBuffers;
  52.     u32 nNextBufferIndex;
  53.     PCMAudioPlayer * pPlayer;
  54. };
  55. /*****************************************************************************
  56.  * Local prototypes.
  57.  *****************************************************************************/
  58. static int     Open        ( vlc_object_t * );
  59. static void    Close       ( vlc_object_t * );
  60. static void    Play        ( aout_instance_t * );
  61. static void*   Thread      ( vlc_object_t * );
  62. static void    InterleaveS16( int16_t *, int16_t * );
  63. /*****************************************************************************
  64.  * Module descriptor
  65.  *****************************************************************************/
  66. vlc_module_begin ()
  67.     set_shortname( "Roku HD1000" )
  68.     set_description( N_("Roku HD1000 audio output") )
  69.     set_capability( "audio output", 100 )
  70.     set_category( CAT_AUDIO )
  71.     set_subcategory( SUBCAT_AUDIO_AOUT )
  72.     set_callbacks( Open, Close )
  73. vlc_module_end ()
  74. /*****************************************************************************
  75.  * Open: open a dummy audio device
  76.  *****************************************************************************/
  77. static int Open( vlc_object_t * p_this )
  78. {
  79.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  80.     struct aout_sys_t * p_sys;
  81.     PCMAudioPlayer * pPlayer;
  82.     int i_volume;
  83.     /* Allocate structure */
  84.     p_aout->output.p_sys = p_sys =
  85.         (aout_sys_t *)malloc( sizeof( aout_sys_t ) );
  86.     if( p_aout->output.p_sys == NULL )
  87.         return VLC_ENOMEM;
  88.     /* New PCMAudioPlayer */
  89.     p_sys->pPlayer = pPlayer = new PCMAudioPlayer();
  90.     if( p_sys->pPlayer == NULL )
  91.     {
  92.         free( p_sys );
  93.         return VLC_ENOMEM;
  94.     }
  95.     /* Get Buffer Requirements */
  96.     if( !pPlayer->GetBufferRequirements( p_sys->nAlignment,
  97.                                          p_sys->nSizeMultiple,
  98.                                          p_sys->nBuffers ) )
  99.     {
  100.         msg_Err( p_aout, "GetBufferRequirements failed" );
  101.         delete pPlayer;
  102.         free( p_sys );
  103.         return VLC_EGENERIC;
  104.     }
  105.     p_sys->nBuffers = __MIN( p_sys->nBuffers, 4 );
  106.     p_sys->ppBuffers = (void **)malloc( p_sys->nBuffers * sizeof( void * ) );
  107.     if( p_sys->ppBuffers == NULL )
  108.     {
  109.         delete pPlayer;
  110.         free( p_sys );
  111.         return VLC_ENOMEM;
  112.     }
  113.     /* Open PCMAudioPlayer */
  114.     p_sys->nBufferSize = FRAME_SIZE * 4;
  115.     if( !pPlayer->Open( p_sys->nBuffers, p_sys->nBufferSize,
  116.                         p_sys->ppBuffers ) )
  117.     {
  118.         msg_Err( p_aout, "Open failed" );
  119.         delete pPlayer;
  120.         free( p_sys->ppBuffers );
  121.         free( p_sys );
  122.         return VLC_EGENERIC;
  123.     }
  124.     p_sys->nNextBufferIndex = 0;
  125.     if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
  126.     {
  127.         p_aout->output.output.i_rate = 44100;
  128.         if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
  129.         {
  130.             msg_Err( p_aout, "SetSampleRate failed" );
  131.             pPlayer->Close();
  132.             delete pPlayer;
  133.             free( p_sys->ppBuffers );
  134.             free( p_sys );
  135.             return VLC_EGENERIC;
  136.         }
  137.     }
  138.     p_aout->output.output.i_format = AOUT_FMT_S16_NE;
  139.     p_aout->output.i_nb_samples = FRAME_SIZE;
  140.     p_aout->output.output.i_physical_channels
  141.             = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
  142.     p_aout->output.pf_play = Play;
  143.     aout_VolumeSoftInit( p_aout );
  144.     i_volume = config_GetInt( p_aout->p_libvlc, "volume" );
  145.     pPlayer->SetVolume( (u32)__MIN( i_volume * 64, 0xFFFF ) );
  146.     /* Create thread and wait for its readiness. */
  147.     if( vlc_thread_create( p_aout, "aout", Thread,
  148.                            VLC_THREAD_PRIORITY_OUTPUT ) )
  149.     {
  150.         msg_Err( p_aout, "cannot create OSS thread (%m)" );
  151.         pPlayer->Close();
  152.         delete pPlayer;
  153.         free( p_sys->ppBuffers );
  154.         free( p_sys );
  155.         return VLC_ETHREAD;
  156.     }
  157.     return VLC_SUCCESS;
  158. }
  159. /*****************************************************************************
  160.  * Close: close our file
  161.  *****************************************************************************/
  162. static void Close( vlc_object_t * p_this )
  163. {
  164.     u32 i;
  165.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  166.     struct aout_sys_t * p_sys = p_aout->output.p_sys;
  167.     vlc_object_kill( p_aout );
  168.     vlc_thread_join( p_aout );
  169.     p_aout->b_die = false;
  170.     do
  171.     {
  172.         i = p_sys->pPlayer->WaitForBuffer();
  173.     } while( i != 0 && i != p_sys->nBuffers );
  174.     p_sys->pPlayer->Close();
  175.     delete p_sys->pPlayer;
  176.     free( p_sys->ppBuffers );
  177.     free( p_sys );
  178. }
  179. /*****************************************************************************
  180.  * Play: do nothing
  181.  *****************************************************************************/
  182. static void Play( aout_instance_t * p_aout )
  183. {
  184. }
  185. /*****************************************************************************
  186.  * Thread: thread used to DMA the data to the device
  187.  *****************************************************************************/
  188. static void* Thread( vlc_object_t *p_this )
  189. {
  190.     aout_instance_t * p_aout = (aout_instance_t*)p_this;
  191.     aout_buffer_t * p_buffer;
  192.     struct aout_sys_t * p_sys = p_aout->output.p_sys;
  193.     PCMAudioPlayer * pPlayer = p_sys->pPlayer;
  194.     int canc = vlc_savecancel ();
  195.     while( vlc_object_alive (p_aout) )
  196.     {
  197.         pPlayer->WaitForBuffer();
  198.         vlc_mutex_lock( &p_aout->output_fifo_lock );
  199.         p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
  200.         vlc_mutex_unlock( &p_aout->output_fifo_lock );
  201. #define i p_sys->nNextBufferIndex
  202.         if( p_buffer == NULL )
  203.         {
  204.             vlc_memset( p_aout, p_sys->ppBuffers[ i ], 0,
  205.                                       p_sys->nBufferSize );
  206.         }
  207.         else
  208.         {
  209.             InterleaveS16( (int16_t *)p_buffer->p_buffer,
  210.                            (int16_t *)p_sys->ppBuffers[ i ] );
  211.             aout_BufferFree( p_buffer );
  212.         }
  213.         if( !pPlayer->QueueBuffer( (s16 *)p_sys->ppBuffers[ i ],
  214.                                    p_sys->nBufferSize / 2 ) )
  215.         {
  216.             msg_Err( p_aout, "QueueBuffer failed" );
  217.         }
  218.         i = (i + 1) % p_sys->nBuffers;
  219. #undef i
  220.     }
  221.     vlc_restorecancel (canc);
  222.     return NULL;
  223. }
  224. /*****************************************************************************
  225.  * InterleaveS16: interleave samples
  226.  *****************************************************************************/
  227. static void InterleaveS16( int16_t * p_in, int16_t * p_out )
  228. {
  229.     for( int i = 0; i < FRAME_SIZE; i++ )
  230.     {
  231.         p_out[ i * 2 + 0 ] = p_in[ i * 2 + 1 ];
  232.         p_out[ i * 2 + 1 ] = p_in[ i * 2 + 0 ];
  233.     }
  234. }