8 #include "subopt-helper.h"
9 #include "libaf/af_format.h"
10 #include "audio_out.h"
11 #include "audio_out_internal.h"
16 static ao_info_t info
=
18 "RAW PCM/WAVE file writer audio output",
28 static char *ao_outputfilename
= NULL
;
29 static int ao_pcm_waveheader
= 1;
31 #define WAV_ID_RIFF 0x46464952 /* "RIFF" */
32 #define WAV_ID_WAVE 0x45564157 /* "WAVE" */
33 #define WAV_ID_FMT 0x20746d66 /* "fmt " */
34 #define WAV_ID_DATA 0x61746164 /* "data" */
35 #define WAV_ID_PCM 0x0001
47 uint32_t bytes_per_second
;
54 /* init with default values */
55 static struct WaveHeader wavhdr
= {
56 le2me_32(WAV_ID_RIFF
),
57 /* same conventions than in sox/wav.c/wavwritehdr() */
58 0, //le2me_32(0x7ffff024),
59 le2me_32(WAV_ID_WAVE
),
68 le2me_32(WAV_ID_DATA
),
69 0, //le2me_32(0x7ffff000)
72 static FILE *fp
= NULL
;
74 // to set/get/query special features/parameters
75 static int control(int cmd
,void *arg
){
79 // open & setup audio device
80 // return: 1=success 0=fail
81 static int init(int rate
,int channels
,int format
,int flags
){
84 {"waveheader", OPT_ARG_BOOL
, &ao_pcm_waveheader
, NULL
},
85 {"file", OPT_ARG_MSTRZ
, &ao_outputfilename
, NULL
},
89 ao_pcm_waveheader
= 1;
91 strdup((ao_pcm_waveheader
)?"audiodump.wav":"audiodump.pcm");
92 if (subopt_parse(ao_subdevice
, subopts
) != 0) {
96 /* bits is only equal to format if (format == 8) or (format == 16);
97 this means that the following "if" is a kludge and should
98 really be a switch to be correct in all cases */
107 format
=AF_FORMAT_S16_LE
;
112 ao_data
.outburst
= 65536;
113 ao_data
.buffersize
= 2*65536;
114 ao_data
.channels
=channels
;
115 ao_data
.samplerate
=rate
;
116 ao_data
.format
=format
;
117 ao_data
.bps
=channels
*rate
*(bits
/8);
119 wavhdr
.channels
= le2me_16(ao_data
.channels
);
120 wavhdr
.sample_rate
= le2me_32(ao_data
.samplerate
);
121 wavhdr
.bytes_per_second
= le2me_32(ao_data
.bps
);
122 wavhdr
.bits
= le2me_16(bits
);
123 wavhdr
.block_align
= le2me_16(ao_data
.channels
* (bits
/ 8));
125 wavhdr
.data_length
=le2me_32(0x7ffff000);
126 wavhdr
.file_length
= wavhdr
.data_length
+ sizeof(wavhdr
) - 8;
128 mp_msg(MSGT_AO
, MSGL_INFO
, MSGTR_AO_PCM_FileInfo
, ao_outputfilename
,
129 (ao_pcm_waveheader
?"WAVE":"RAW PCM"), rate
,
130 (channels
> 1) ? "Stereo" : "Mono", af_fmt2str_short(format
));
131 mp_msg(MSGT_AO
, MSGL_INFO
, MSGTR_AO_PCM_HintInfo
);
133 fp
= fopen(ao_outputfilename
, "wb");
135 if(ao_pcm_waveheader
){ /* Reserve space for wave header */
136 fwrite(&wavhdr
,sizeof(wavhdr
),1,fp
);
137 wavhdr
.file_length
=wavhdr
.data_length
=0;
141 mp_msg(MSGT_AO
, MSGL_ERR
, MSGTR_AO_PCM_CantOpenOutputFile
,
146 // close audio device
147 static void uninit(int immed
){
149 if(ao_pcm_waveheader
&& fseek(fp
, 0, SEEK_SET
) == 0){ /* Write wave header */
150 wavhdr
.file_length
= wavhdr
.data_length
+ sizeof(wavhdr
) - 8;
151 wavhdr
.file_length
= le2me_32(wavhdr
.file_length
);
152 wavhdr
.data_length
= le2me_32(wavhdr
.data_length
);
153 fwrite(&wavhdr
,sizeof(wavhdr
),1,fp
);
156 if (ao_outputfilename
)
157 free(ao_outputfilename
);
158 ao_outputfilename
= NULL
;
161 // stop playing and empty buffers (for seeking/pause)
166 // stop playing, keep buffers (for pause)
167 static void audio_pause()
169 // for now, just call reset();
173 // resume playing, after audio_pause()
174 static void audio_resume()
178 // return: how many bytes can be played without blocking
179 static int get_space(){
182 return ao_data
.pts
< vo_pts
? ao_data
.outburst
: 0;
183 return ao_data
.outburst
;
186 // plays 'len' bytes of 'data'
187 // it should round it down to outburst*n
188 // return: number of bytes played
189 static int play(void* data
,int len
,int flags
){
191 // let libaf to do the conversion...
193 //#ifdef WORDS_BIGENDIAN
194 if (ao_data
.format
== AFMT_S16_LE
) {
195 unsigned short *buffer
= (unsigned short *) data
;
197 for(i
= 0; i
< len
/2; ++i
) {
198 buffer
[i
] = le2me_16(buffer
[i
]);
203 //printf("PCM: Writing chunk!\n");
204 fwrite(data
,len
,1,fp
);
206 if(ao_pcm_waveheader
)
207 wavhdr
.data_length
+= len
;
212 // return: delay in seconds between first and last sample in buffer
213 static float get_delay(){