Some typo fixes in svn-howto
[mplayer/glamo.git] / libao2 / ao_pcm.c
blob6aa1fcb4db63b78e6b02f48d9b4f1bb525b81266
1 #include "config.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include "libavutil/common.h"
8 #include "mpbswap.h"
9 #include "subopt-helper.h"
10 #include "libaf/af_format.h"
11 #include "audio_out.h"
12 #include "audio_out_internal.h"
13 #include "mp_msg.h"
14 #include "help_mp.h"
17 static ao_info_t info =
19 "RAW PCM/WAVE file writer audio output",
20 "pcm",
21 "Atmosfear",
25 LIBAO_EXTERN(pcm)
27 extern int vo_pts;
29 static char *ao_outputfilename = NULL;
30 static int ao_pcm_waveheader = 1;
31 static int fast = 0;
33 #define WAV_ID_RIFF 0x46464952 /* "RIFF" */
34 #define WAV_ID_WAVE 0x45564157 /* "WAVE" */
35 #define WAV_ID_FMT 0x20746d66 /* "fmt " */
36 #define WAV_ID_DATA 0x61746164 /* "data" */
37 #define WAV_ID_PCM 0x0001
39 struct WaveHeader
41 uint32_t riff;
42 uint32_t file_length;
43 uint32_t wave;
44 uint32_t fmt;
45 uint32_t fmt_length;
46 uint16_t fmt_tag;
47 uint16_t channels;
48 uint32_t sample_rate;
49 uint32_t bytes_per_second;
50 uint16_t block_align;
51 uint16_t bits;
52 uint32_t data;
53 uint32_t data_length;
56 /* init with default values */
57 static struct WaveHeader wavhdr;
59 static FILE *fp = NULL;
61 // to set/get/query special features/parameters
62 static int control(int cmd,void *arg){
63 return -1;
66 // open & setup audio device
67 // return: 1=success 0=fail
68 static int init(int rate,int channels,int format,int flags){
69 int bits;
70 opt_t subopts[] = {
71 {"waveheader", OPT_ARG_BOOL, &ao_pcm_waveheader, NULL},
72 {"file", OPT_ARG_MSTRZ, &ao_outputfilename, NULL},
73 {"fast", OPT_ARG_BOOL, &fast, NULL},
74 {NULL}
76 // set defaults
77 ao_pcm_waveheader = 1;
79 if (subopt_parse(ao_subdevice, subopts) != 0) {
80 return 0;
82 if (!ao_outputfilename){
83 ao_outputfilename =
84 strdup(ao_pcm_waveheader?"audiodump.wav":"audiodump.pcm");
87 /* bits is only equal to format if (format == 8) or (format == 16);
88 this means that the following "if" is a kludge and should
89 really be a switch to be correct in all cases */
91 bits=8;
92 switch(format){
93 case AF_FORMAT_S8:
94 format=AF_FORMAT_U8;
95 case AF_FORMAT_U8:
96 break;
97 default:
98 format=AF_FORMAT_S16_LE;
99 bits=16;
100 break;
103 ao_data.outburst = 65536;
104 ao_data.buffersize= 2*65536;
105 ao_data.channels=channels;
106 ao_data.samplerate=rate;
107 ao_data.format=format;
108 ao_data.bps=channels*rate*(bits/8);
110 wavhdr.riff = le2me_32(WAV_ID_RIFF);
111 wavhdr.wave = le2me_32(WAV_ID_WAVE);
112 wavhdr.fmt = le2me_32(WAV_ID_FMT);
113 wavhdr.fmt_length = le2me_32(16);
114 wavhdr.fmt_tag = le2me_16(WAV_ID_PCM);
115 wavhdr.channels = le2me_16(ao_data.channels);
116 wavhdr.sample_rate = le2me_32(ao_data.samplerate);
117 wavhdr.bytes_per_second = le2me_32(ao_data.bps);
118 wavhdr.bits = le2me_16(bits);
119 wavhdr.block_align = le2me_16(ao_data.channels * (bits / 8));
121 wavhdr.data = le2me_32(WAV_ID_DATA);
122 wavhdr.data_length=le2me_32(0x7ffff000);
123 wavhdr.file_length = wavhdr.data_length + sizeof(wavhdr) - 8;
125 mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_FileInfo, ao_outputfilename,
126 (ao_pcm_waveheader?"WAVE":"RAW PCM"), rate,
127 (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format));
128 mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_PCM_HintInfo);
130 fp = fopen(ao_outputfilename, "wb");
131 if(fp) {
132 if(ao_pcm_waveheader){ /* Reserve space for wave header */
133 fwrite(&wavhdr,sizeof(wavhdr),1,fp);
134 wavhdr.file_length=wavhdr.data_length=0;
136 return 1;
138 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_PCM_CantOpenOutputFile,
139 ao_outputfilename);
140 return 0;
143 // close audio device
144 static void uninit(int immed){
146 if(ao_pcm_waveheader && fseek(fp, 0, SEEK_SET) == 0){ /* Write wave header */
147 wavhdr.file_length = wavhdr.data_length + sizeof(wavhdr) - 8;
148 wavhdr.file_length = le2me_32(wavhdr.file_length);
149 wavhdr.data_length = le2me_32(wavhdr.data_length);
150 fwrite(&wavhdr,sizeof(wavhdr),1,fp);
152 fclose(fp);
153 if (ao_outputfilename)
154 free(ao_outputfilename);
155 ao_outputfilename = NULL;
158 // stop playing and empty buffers (for seeking/pause)
159 static void reset(void){
163 // stop playing, keep buffers (for pause)
164 static void audio_pause(void)
166 // for now, just call reset();
167 reset();
170 // resume playing, after audio_pause()
171 static void audio_resume(void)
175 // return: how many bytes can be played without blocking
176 static int get_space(void){
178 if(vo_pts)
179 return ao_data.pts < vo_pts + fast * 30000 ? ao_data.outburst : 0;
180 return ao_data.outburst;
183 // plays 'len' bytes of 'data'
184 // it should round it down to outburst*n
185 // return: number of bytes played
186 static int play(void* data,int len,int flags){
188 // let libaf to do the conversion...
189 #if 0
190 //#ifdef WORDS_BIGENDIAN
191 if (ao_data.format == AFMT_S16_LE) {
192 unsigned short *buffer = (unsigned short *) data;
193 register int i;
194 for(i = 0; i < len/2; ++i) {
195 buffer[i] = le2me_16(buffer[i]);
198 #endif
200 //printf("PCM: Writing chunk!\n");
201 fwrite(data,len,1,fp);
203 if(ao_pcm_waveheader)
204 wavhdr.data_length += len;
206 return len;
209 // return: delay in seconds between first and last sample in buffer
210 static float get_delay(void){
212 return 0.0;