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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * file.c : audio output which writes the samples to a file
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 the VideoLAN team
  5.  * $Id: f6f851aa436c976444c80f1d8ed5e6adf7f536ad $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@netcourrier.com>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <errno.h>
  31. #include <vlc_common.h>
  32. #include <vlc_plugin.h>
  33. #include <vlc_aout.h>
  34. #include <vlc_codecs.h> /* WAVEHEADER */
  35. #include <vlc_charset.h>
  36. #define FRAME_SIZE 2048
  37. #define A52_FRAME_NB 1536
  38. /*****************************************************************************
  39.  * aout_sys_t: audio output method descriptor
  40.  *****************************************************************************
  41.  * This structure is part of the audio output thread descriptor.
  42.  * It describes the direct sound specific properties of an audio device.
  43.  *****************************************************************************/
  44. struct aout_sys_t
  45. {
  46.     FILE     * p_file;
  47.     bool b_add_wav_header;
  48.     WAVEHEADER waveh;                      /* Wave header of the output file */
  49. };
  50. #define CHANNELS_MAX 6
  51. static const int pi_channels_maps[CHANNELS_MAX+1] =
  52. {
  53.     0,
  54.     AOUT_CHAN_CENTER,
  55.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  56.     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  57.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
  58.      | AOUT_CHAN_REARRIGHT,
  59.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  60.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
  61.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  62.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
  63. };
  64. /*****************************************************************************
  65.  * Local prototypes.
  66.  *****************************************************************************/
  67. static int     Open        ( vlc_object_t * );
  68. static void    Close       ( vlc_object_t * );
  69. static void    Play        ( aout_instance_t * );
  70. /*****************************************************************************
  71.  * Module descriptor
  72.  *****************************************************************************/
  73. #define FORMAT_TEXT N_("Output format")
  74. #define FORMAT_LONGTEXT N_("One of "u8", "s8", "u16", "s16", " 
  75.     ""u16_le", "s16_le", "u16_be", "s16_be", "fixed32", " 
  76.     ""float32" or "spdif"")
  77. #define CHANNELS_TEXT N_("Number of output channels")
  78. #define CHANNELS_LONGTEXT N_("By default, all the channels of the incoming " 
  79.     "will be saved but you can restrict the number of channels here.")
  80. #define WAV_TEXT N_("Add WAVE header")
  81. #define WAV_LONGTEXT N_("Instead of writing a raw file, you can add a WAV " 
  82.                         "header to the file.")
  83. static const char *const format_list[] = { "u8", "s8", "u16", "s16", "u16_le",
  84.                                      "s16_le", "u16_be", "s16_be", "fixed32",
  85.                                      "float32", "spdif" };
  86. static const int format_int[] = { VLC_FOURCC('u','8',' ',' '),
  87.                                   VLC_FOURCC('s','8',' ',' '),
  88.                                   AOUT_FMT_U16_NE, AOUT_FMT_S16_NE,
  89.                                   VLC_FOURCC('u','1','6','l'),
  90.                                   VLC_FOURCC('s','1','6','l'),
  91.                                   VLC_FOURCC('u','1','6','b'),
  92.                                   VLC_FOURCC('s','1','6','b'),
  93.                                   VLC_FOURCC('f','i','3','2'),
  94.                                   VLC_FOURCC('f','l','3','2'),
  95.                                   VLC_FOURCC('s','p','i','f') };
  96. #define FILE_TEXT N_("Output file")
  97. #define FILE_LONGTEXT N_("File to which the audio samples will be written to. ("-" for stdout")
  98. vlc_module_begin ()
  99.     set_description( N_("File audio output") )
  100.     set_shortname( N_("File") )
  101.     set_category( CAT_AUDIO )
  102.     set_subcategory( SUBCAT_AUDIO_AOUT )
  103.     add_string( "audiofile-format", "s16", NULL,
  104.                 FORMAT_TEXT, FORMAT_LONGTEXT, true )
  105.         change_string_list( format_list, 0, 0 )
  106.     add_integer( "audiofile-channels", 0, NULL,
  107.                  CHANNELS_TEXT, CHANNELS_LONGTEXT, true )
  108.     add_file( "audiofile-file", "audiofile.wav", NULL, FILE_TEXT,
  109.               FILE_LONGTEXT, false )
  110.     add_bool( "audiofile-wav", 1, NULL, WAV_TEXT, WAV_LONGTEXT, true )
  111.     set_capability( "audio output", 0 )
  112.     add_shortcut( "file" )
  113.     add_shortcut( "audiofile" )
  114.     set_callbacks( Open, Close )
  115. vlc_module_end ()
  116. /*****************************************************************************
  117.  * Open: open a dummy audio device
  118.  *****************************************************************************/
  119. static int Open( vlc_object_t * p_this )
  120. {
  121.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  122.     char * psz_name, * psz_format;
  123.     const char * const * ppsz_compare = format_list;
  124.     int i_channels, i = 0;
  125.     psz_name = var_CreateGetString( p_this, "audiofile-file" );
  126.     if( !psz_name || !*psz_name )
  127.     {
  128.         msg_Err( p_aout, "you need to specify an output file name" );
  129.         free( psz_name );
  130.         return VLC_EGENERIC;
  131.     }
  132.     /* Allocate structure */
  133.     p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
  134.     if( p_aout->output.p_sys == NULL )
  135.         return VLC_ENOMEM;
  136.     if( !strcmp( psz_name, "-" ) )
  137.         p_aout->output.p_sys->p_file = stdout;
  138.     else
  139.         p_aout->output.p_sys->p_file = utf8_fopen( psz_name, "wb" );
  140.     free( psz_name );
  141.     if ( p_aout->output.p_sys->p_file == NULL )
  142.     {
  143.         free( p_aout->output.p_sys );
  144.         return VLC_EGENERIC;
  145.     }
  146.     p_aout->output.pf_play = Play;
  147.     /* Audio format */
  148.     psz_format = var_CreateGetString( p_this, "audiofile-format" );
  149.     while ( *ppsz_compare != NULL )
  150.     {
  151.         if ( !strncmp( *ppsz_compare, psz_format, strlen(*ppsz_compare) ) )
  152.         {
  153.             break;
  154.         }
  155.         ppsz_compare++; i++;
  156.     }
  157.     if ( *ppsz_compare == NULL )
  158.     {
  159.         msg_Err( p_aout, "cannot understand the format string (%s)",
  160.                  psz_format );
  161.         if( p_aout->output.p_sys->p_file != stdout )
  162.             fclose( p_aout->output.p_sys->p_file );
  163.         free( p_aout->output.p_sys );
  164.         free( psz_format );
  165.         return VLC_EGENERIC;
  166.     }
  167.     free( psz_format );
  168.     p_aout->output.output.i_format = format_int[i];
  169.     if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
  170.     {
  171.         p_aout->output.i_nb_samples = A52_FRAME_NB;
  172.         p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
  173.         p_aout->output.output.i_frame_length = A52_FRAME_NB;
  174.         aout_VolumeNoneInit( p_aout );
  175.     }
  176.     else
  177.     {
  178.         p_aout->output.i_nb_samples = FRAME_SIZE;
  179.         aout_VolumeSoftInit( p_aout );
  180.     }
  181.     /* Channels number */
  182.     i_channels = var_CreateGetInteger( p_this, "audiofile-channels" );
  183.     if( i_channels > 0 && i_channels <= CHANNELS_MAX )
  184.     {
  185.         p_aout->output.output.i_physical_channels =
  186.             pi_channels_maps[i_channels];
  187.     }
  188.     /* WAV header */
  189.     p_aout->output.p_sys->b_add_wav_header = var_CreateGetBool( p_this,
  190.                                                         "audiofile-wav" );
  191.     if( p_aout->output.p_sys->b_add_wav_header )
  192.     {
  193.         /* Write wave header */
  194.         WAVEHEADER *wh = &p_aout->output.p_sys->waveh;
  195.         memset( wh, 0, sizeof(wh) );
  196.         switch( p_aout->output.output.i_format )
  197.         {
  198.         case VLC_FOURCC('f','l','3','2'):
  199.             wh->Format     = WAVE_FORMAT_IEEE_FLOAT;
  200.             wh->BitsPerSample = sizeof(float) * 8;
  201.             break;
  202.         case VLC_FOURCC('u','8',' ',' '):
  203.             wh->Format     = WAVE_FORMAT_PCM;
  204.             wh->BitsPerSample = 8;
  205.             break;
  206.         case VLC_FOURCC('s','1','6','l'):
  207.         default:
  208.             wh->Format     = WAVE_FORMAT_PCM;
  209.             wh->BitsPerSample = 16;
  210.             break;
  211.         }
  212.         wh->MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
  213.         wh->Length = 0;                    /* temp, to be filled in as we go */
  214.         wh->ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
  215.         wh->SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
  216.         wh->SubChunkLength = 16;
  217.         wh->Modus = aout_FormatNbChannels( &p_aout->output.output );
  218.         wh->SampleFreq = p_aout->output.output.i_rate;
  219.         wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 );
  220.         wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq;
  221.         wh->DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
  222.         wh->DataLength = 0;                /* temp, to be filled in as we go */
  223.         /* Header -> little endian format */
  224.         SetWLE( &wh->Format, wh->Format );
  225.         SetWLE( &wh->BitsPerSample, wh->BitsPerSample );
  226.         SetDWLE( &wh->SubChunkLength, wh->SubChunkLength );
  227.         SetWLE( &wh->Modus, wh->Modus );
  228.         SetDWLE( &wh->SampleFreq, wh->SampleFreq );
  229.         SetWLE( &wh->BytesPerSample, wh->BytesPerSample );
  230.         SetDWLE( &wh->BytesPerSec, wh->BytesPerSec );
  231.         if( fwrite( wh, sizeof(WAVEHEADER), 1,
  232.                     p_aout->output.p_sys->p_file ) != 1 )
  233.         {
  234.             msg_Err( p_aout, "write error (%m)" );
  235.         }
  236.     }
  237.     return 0;
  238. }
  239. /*****************************************************************************
  240.  * Close: close our file
  241.  *****************************************************************************/
  242. static void Close( vlc_object_t * p_this )
  243. {
  244.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  245.     msg_Dbg( p_aout, "closing audio file" );
  246.     if( p_aout->output.p_sys->b_add_wav_header )
  247.     {
  248.         /* Update Wave Header */
  249.         p_aout->output.p_sys->waveh.Length =
  250.             p_aout->output.p_sys->waveh.DataLength + sizeof(WAVEHEADER) - 4;
  251.         /* Write Wave Header */
  252.         if( fseek( p_aout->output.p_sys->p_file, 0, SEEK_SET ) )
  253.         {
  254.             msg_Err( p_aout, "seek error (%m)" );
  255.         }
  256.         /* Header -> little endian format */
  257.         SetDWLE( &p_aout->output.p_sys->waveh.Length,
  258.                  p_aout->output.p_sys->waveh.Length );
  259.         SetDWLE( &p_aout->output.p_sys->waveh.DataLength,
  260.                  p_aout->output.p_sys->waveh.DataLength );
  261.         if( fwrite( &p_aout->output.p_sys->waveh, sizeof(WAVEHEADER), 1,
  262.                     p_aout->output.p_sys->p_file ) != 1 )
  263.         {
  264.             msg_Err( p_aout, "write error (%m)" );
  265.         }
  266.     }
  267.     if( p_aout->output.p_sys->p_file != stdout )
  268.         fclose( p_aout->output.p_sys->p_file );
  269.     free( p_aout->output.p_sys );
  270. }
  271. /*****************************************************************************
  272.  * Play: pretend to play a sound
  273.  *****************************************************************************/
  274. static void Play( aout_instance_t * p_aout )
  275. {
  276.     aout_buffer_t * p_buffer;
  277.     p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
  278.     if( fwrite( p_buffer->p_buffer, p_buffer->i_nb_bytes, 1,
  279.                 p_aout->output.p_sys->p_file ) != 1 )
  280.     {
  281.         msg_Err( p_aout, "write error (%m)" );
  282.     }
  283.     if( p_aout->output.p_sys->b_add_wav_header )
  284.     {
  285.         /* Update Wave Header */
  286.         p_aout->output.p_sys->waveh.DataLength += p_buffer->i_nb_bytes;
  287.     }
  288.     aout_BufferFree( p_buffer );
  289. }