comparison music2/wavfile.cc @ 0:223b71206888

Initial import
author thib
date Fri, 01 Aug 2008 16:32:45 +0000
parents
children fa8511a21d05
comparison
equal deleted inserted replaced
-1:000000000000 0:223b71206888
1 /*
2 * wavfile.c WAV file check
3 *
4 * Copyright: wavfile.c (c) Erik de Castro Lopo erikd@zip.com.au
5 *
6 * Modified : 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
7 * 1998- <masaki-c@is.aist-nara.ac.jp>
8 * 2000- Kazunori Ueno(JAGARL) <jagarl@createor.club.ne.jp>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include "wavfile.h"
34 #include "system/file.h"
35 #include "music.h"
36
37 #define BUFFERSIZE 1024
38 #define PCM_WAVE_FORMAT 1
39
40 /*******************************************************
41 **
42 ** WAVE Header
43 */
44
45 inline int LittleEndian_getDW(const char *b,int index) {
46 int c0, c1, c2, c3;
47 int d0, d1;
48 c0 = *(const unsigned char*)(b + index + 0);
49 c1 = *(const unsigned char*)(b + index + 1);
50 c2 = *(const unsigned char*)(b + index + 2);
51 c3 = *(const unsigned char*)(b + index + 3);
52 d0 = c0 + (c1 << 8);
53 d1 = c2 + (c3 << 8);
54 return d0 + (d1 << 16);
55 }
56
57 inline int LittleEndian_get3B(const char *b,int index) {
58 int c0, c1, c2;
59 c0 = *(const unsigned char*)(b + index + 0);
60 c1 = *(const unsigned char*)(b + index + 1);
61 c2 = *(const unsigned char*)(b + index + 2);
62 return c0 + (c1 << 8) + (c2 << 16);
63 }
64
65 inline int LittleEndian_getW(const char *b,int index) {
66 int c0, c1;
67 c0 = *(const unsigned char*)(b + index + 0);
68 c1 = *(const unsigned char*)(b + index + 1);
69 return c0 + (c1 << 8);
70 }
71
72 inline void LittleEndian_putW(int num, char *b, int index) {
73 int c0, c1;
74 num %= 65536;
75 c0 = num % 256;
76 c1 = num / 256;
77 b[index] = c0; b[index+1] = c1;
78 }
79
80 typedef struct
81 { u_long dwSize ;
82 u_short wFormatTag ;
83 u_short wChannels ;
84 u_long dwSamplesPerSec ;
85 u_long dwAvgBytesPerSec ;
86 u_short wBlockAlign ;
87 u_short wBitsPerSample ;
88 } WAVEFORMAT ;
89
90 typedef struct
91 { char RiffID [4] ;
92 u_long RiffSize ;
93 char WaveID [4] ;
94 char FmtID [4] ;
95 u_long FmtSize ;
96 u_short wFormatTag ;
97 u_short nChannels ;
98 u_long nSamplesPerSec ;
99 u_long nAvgBytesPerSec ;
100 u_short nBlockAlign ;
101 u_short wBitsPerSample ;
102 char DataID [4] ;
103 u_long nDataBytes ;
104 } WAVE_HEADER ;
105
106
107 static void waveFormatCopy( WAVEFORMAT* wav, char *ptr );
108 static char* findchunk (char* s1, char* s2, size_t n) ;
109
110 static int WaveHeaderCheck (char *wave_buf,int* channels, u_long* samplerate, int* samplebits, u_long* samples,u_long* datastart)
111 {
112 static WAVEFORMAT waveformat ;
113 char* ptr ;
114 u_long databytes ;
115
116 if (findchunk (wave_buf, "RIFF", BUFFERSIZE) != wave_buf) {
117 fprintf(stderr, "Bad format: Cannot find RIFF file marker");
118 return WR_BADRIFF ;
119 }
120
121 if (! findchunk (wave_buf, "WAVE", BUFFERSIZE)) {
122 fprintf(stderr, "Bad format: Cannot find WAVE file marker");
123 return WR_BADWAVE ;
124 }
125
126 ptr = findchunk (wave_buf, "fmt ", BUFFERSIZE) ;
127
128 if (! ptr) {
129 fprintf(stderr, "Bad format: Cannot find 'fmt' file marker");
130 return WR_BADFORMAT ;
131 }
132
133 ptr += 4 ; /* Move past "fmt ".*/
134 waveFormatCopy( &waveformat, ptr );
135
136 if (waveformat.dwSize != (sizeof (WAVEFORMAT) - sizeof (u_long))) {
137 /* fprintf(stderr, "Bad format: Bad fmt size"); */
138 /* return WR_BADFORMATSIZE ; */
139 }
140
141 if (waveformat.wFormatTag != PCM_WAVE_FORMAT) {
142 fprintf(stderr, "Only supports PCM wave format");
143 return WR_NOTPCMFORMAT ;
144 }
145
146 ptr = findchunk (wave_buf, "data", BUFFERSIZE) ;
147
148 if (! ptr) {
149 fprintf(stderr,"Bad format: unable to find 'data' file marker");
150 return WR_NODATACHUNK ;
151 }
152
153 ptr += 4 ; /* Move past "data".*/
154 databytes = LittleEndian_getDW(ptr, 0);
155
156 /* Everything is now cool, so fill in output data.*/
157
158 *channels = waveformat.wChannels;
159 *samplerate = waveformat.dwSamplesPerSec ;
160 *samplebits = waveformat.wBitsPerSample ;
161 *samples = databytes / waveformat.wBlockAlign ;
162
163 *datastart = (u_long)(ptr) + 4;
164
165 if (waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / waveformat.wBlockAlign) {
166 fprintf(stderr, "Bad file format");
167 return WR_BADFORMATDATA ;
168 }
169
170 if (waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / waveformat.wChannels / ((waveformat.wBitsPerSample == 16) ? 2 : 1)) {
171 fprintf(stderr, "Bad file format");
172 return WR_BADFORMATDATA ;
173 }
174
175 return 0 ;
176 } ; /* WaveHeaderCheck*/
177
178
179 static char* findchunk (char* pstart, char* fourcc, size_t n)
180 { char *pend ;
181 int k, test ;
182
183 pend = pstart + n ;
184
185 while (pstart < pend)
186 {
187 if (*pstart == *fourcc) /* found match for first char*/
188 { test = 1 ;
189 for (k = 1 ; fourcc [k] != 0 ; k++)
190 test = (test ? ( pstart [k] == fourcc [k] ) : 0) ;
191 if (test)
192 return pstart ;
193 } ; /* if*/
194 pstart ++ ;
195 } ; /* while lpstart*/
196
197 return NULL ;
198 } ; /* findchuck*/
199
200 static void waveFormatCopy( WAVEFORMAT* wav, char *ptr ) {
201 wav->dwSize = LittleEndian_getDW( ptr, 0 );
202 wav->wFormatTag = LittleEndian_getW( ptr, 4 );
203 wav->wChannels = LittleEndian_getW( ptr, 6 );
204 wav->dwSamplesPerSec = LittleEndian_getDW( ptr, 8 );
205 wav->dwAvgBytesPerSec = LittleEndian_getDW( ptr, 12 );
206 wav->wBlockAlign = LittleEndian_getW( ptr, 16 );
207 wav->wBitsPerSample = LittleEndian_getW( ptr, 18 );
208 }
209
210 static char* WavGetInfo(WAVFILE* wfile, char *data) {
211 int e; /* Saved errno value */
212 int channels; /* Channels recorded in this wav file */
213 u_long samplerate; /* Sampling rate */
214 int sample_bits; /* data bit size (8/12/16) */
215 u_long samples; /* The number of samples in this file */
216 u_long datastart; /* The offset to the wav data */
217
218 if ( (e = WaveHeaderCheck(data,
219 &channels,&samplerate,
220 &sample_bits,&samples,&datastart) != 0 )) {
221 fprintf(stderr,"WavGetInfo(): Reading WAV header\n");
222 return 0;
223 }
224
225 /*
226 * Copy WAV data over to WAVFILE struct:
227 */
228 wfile->wavinfo.Channels = channels;
229
230 wfile->wavinfo.SamplingRate = (unsigned int) samplerate;
231 wfile->wavinfo.DataBits = (unsigned short) sample_bits;
232
233 return (char *) datastart;
234 }
235
236 /************************************************************:
237 **
238 ** WAVFILE stream reader
239 */
240
241 #include<SDL_mixer.h>
242 WAVFILE::WAVFILE(void) {
243 wavinfo.SamplingRate=0;
244 wavinfo.Channels=1;
245 wavinfo.DataBits=0;
246 }
247
248 int WAVFILE_Stream::Read(char* in_buf, int blksize, int length) {
249 /* ファイルの読み込み */
250 if (data_length == 0 && stream_length == 0) return -1;
251 /* wf->data にデータの残りがあればそれも読み込む */
252 if (data_length > blksize*length) {
253 memcpy(in_buf, data, blksize*length);
254 data += blksize * length;
255 data_length -= blksize * length;
256 return length;
257 }
258 memcpy(in_buf, data, data_length);
259 if (stream_length != -1 && stream_length < blksize*length-data_length) {
260 length = (stream_length+data_length+blksize-1)/blksize;
261 }
262 int read_len = 0;
263 if (blksize*length-data_length > 0) {
264 read_len = fread(in_buf+data_length, 1, blksize*length-data_length, stream);
265 if (stream_length != -1 && stream_length > read_len) stream_length -= read_len;
266 if (feof(stream)) stream_length = 0; // end of file
267 } else {
268 stream_length = 0; // all data were read
269 }
270 int blklen = (read_len + data_length) / blksize;
271 data_length = 0;
272 return blklen;
273 }
274 void WAVFILE_Stream::Seek(int count) {
275 int blksize = 1;
276 /* block size の設定 */
277 blksize *= wavinfo.Channels * (wavinfo.DataBits/8);
278 data_length = 0;
279 stream_length = stream_length_orig - stream_top - count*blksize;
280 fseek(stream, count*blksize+stream_top, 0);
281 }
282 WAVFILE_Stream::WAVFILE_Stream(FILE* _stream, int _length) {
283 stream = _stream;
284 stream_length = _length;
285 stream_length_orig = _length;
286 data_orig = new char[1024];
287 data = data_orig;
288 data_length = 1024;
289 if (stream_length != -1 && stream_length < data_length) {
290 data_length = stream_length;
291 }
292 fread(data, data_length, 1, stream);
293 if (stream_length != -1)
294 stream_length -= data_length;
295 data = WavGetInfo(this, data);
296 if (data == 0) {
297 stream_length = 0;
298 data_length = 0;
299 return;
300 }
301 stream_top = data - data_orig;
302 data_length -= data - data_orig;
303 return;
304 }
305 WAVFILE_Stream::~WAVFILE_Stream() {
306 if (data_orig) delete data_orig;
307 if (stream) fclose(stream);
308 return;
309 }
310 /************************************************************:
311 **
312 ** WAVE format converter with SDL_audio
313 */
314 WAVFILE* WAVFILE::MakeConverter(WAVFILE* new_reader) {
315 bool need = false;
316 if (new_reader->wavinfo.SamplingRate != freq) need = true;
317 if (new_reader->wavinfo.Channels != channels) need = true;
318 if (format == AUDIO_S8) {
319 if (new_reader->wavinfo.DataBits != 8) need = true;
320 } else if (format == AUDIO_S16) {
321 if (new_reader->wavinfo.DataBits != 16) need = true;
322 } else {
323 need = true;
324 }
325 if (!need) return new_reader;
326 /* 変換もとのフォーマットを得る */
327 int from_format;
328 if (new_reader->wavinfo.DataBits == 8) from_format = AUDIO_S8;
329 else from_format = AUDIO_S16;
330 SDL_AudioCVT* cvt = new SDL_AudioCVT;
331 int ret = SDL_BuildAudioCVT(cvt, from_format, new_reader->wavinfo.Channels, freq,
332 format, 2, freq);
333 if (ret == -1) {
334 delete cvt;
335 fprintf(stderr,"Cannot make wave file converter!!!\n");
336 return new_reader;
337 }
338 WAVFILE_Converter* conv = new WAVFILE_Converter(new_reader, cvt);
339 return conv;
340 }
341 WAVFILE_Converter::WAVFILE_Converter(WAVFILE* _orig, SDL_AudioCVT* _cvt) {
342 original = _orig;
343 cvt = _cvt;
344 //datasize = 4096*4;
345 datasize = 48000;
346 cvt->buf = new Uint8[datasize*cvt->len_mult];
347 cvt->len = 0;
348 tmpbuf = new char[datasize*cvt->len_mult + 1024];
349 memset(tmpbuf, 0, datasize*cvt->len_mult+1024);
350 };
351
352 static int conv_wave_rate(short* in_buf, int length, int in_rate, int out_rate, char* tmpbuf);
353 WAVFILE_Converter::~WAVFILE_Converter() {
354 if (cvt) {
355 if (cvt->buf) delete cvt->buf;
356 delete cvt;
357 cvt = 0;
358 }
359 if (original) delete original;
360 original = 0;
361 }
362 int WAVFILE_Converter::Read(char* buf, int blksize, int blklen) {
363 if (original == 0 || cvt == 0) return -1;
364 int copied_length = 0;
365 if (cvt->len < blksize*blklen) {
366 memcpy(buf, cvt->buf, cvt->len);
367 copied_length += cvt->len;
368 do {
369 int cnt = original->Read((char*)cvt->buf, 1, datasize);
370 if (cnt <= 0) {
371 cvt->len = 0;
372 break;
373 }
374 cvt->len = cnt;
375 SDL_ConvertAudio(cvt);
376 if (freq < original->wavinfo.SamplingRate) { // rate conversion は SDL_ConvertAudio ではうまく行かない
377 // 48000Hz -> 44100Hz or 22050Hz などを想定
378 // 長さは短くなるはずなので、特に処理はなし
379 cvt->len = conv_wave_rate( (short*)(cvt->buf), cvt->len_cvt/4, original->wavinfo.SamplingRate, freq, tmpbuf);
380 cvt->len *= 4;
381 } else {
382 cvt->len = cvt->len_cvt;
383 }
384 if (cvt->len+copied_length > blksize*blklen) break;
385 memcpy(buf+copied_length, cvt->buf, cvt->len);
386 copied_length += cvt->len;
387 } while(1);
388 }
389 if (cvt->len == 0 && copied_length == 0) return -1;
390 else if (cvt->len > 0) {
391 int len = blksize * blklen - copied_length;
392 memcpy(buf+copied_length, cvt->buf, len);
393 memmove(cvt->buf, cvt->buf+len, cvt->len-len);
394 copied_length += len;
395 cvt->len -= len;
396 }
397 return copied_length / blksize;
398 }
399 /* format は signed, 16bit, little endian, stereo と決めうち
400 ** 場合によっていは big endian になることもあるかも。
401 */
402 static int conv_wave_rate(short* in_buf, int length, int in_rate, int out_rate, char* tmpbuf) {
403 int input_rate = in_rate;
404 int output_rate = out_rate;
405 double input_rate_d = input_rate, output_rate_d = output_rate;
406 double dtime; int outlen; short* out, * out_orig; int next_sample1, next_sample2;
407 short* in_buf_orig = in_buf;
408 int i; int time;
409
410 if (input_rate == output_rate) return length;
411 if (length <= 0) return 0;
412 /* 一般の周波数変換:線型補完 */
413 int& first_flag = *(int*)(tmpbuf);
414 int& prev_time = *(int*)(tmpbuf+4);
415 int& prev_sample1 = *(int*)(tmpbuf+8);
416 int& prev_sample2 = *(int*)(tmpbuf+12);
417 out = (short*)(tmpbuf+16);
418 /* 初めてならデータを初期化 */
419 if (first_flag == 0) {
420 first_flag = 1;
421 prev_time = 0;
422 prev_sample1 = short(read_little_endian_short((char*)(in_buf++)));
423 prev_sample2 = short(read_little_endian_short((char*)(in_buf++)));
424 length--;
425 }
426 /* 今回作成するデータ量を得る */
427 dtime = prev_time + length * output_rate_d;
428 outlen = (int)(dtime / input_rate_d);
429 out_orig = out;
430 if (first_flag == 1) {
431 write_little_endian_short((char*)out, prev_sample1);
432 out++;
433 write_little_endian_short((char*)out, prev_sample2);
434 out++;
435 }
436 dtime -= input_rate_d*outlen; /* 次の prev_time */
437
438 time=0;
439 next_sample1 = short(read_little_endian_short((char*)(in_buf++)));
440 next_sample2 = short(read_little_endian_short((char*)(in_buf++)));
441 for (i=0; i<outlen; i++) {
442 /* double で計算してみたけどそう簡単には高速化は無理らしい */
443 /* なお、変換は 1分のデータに1秒程度かかる(Celeron 700MHz) */
444 time += input_rate;
445 while(time-prev_time>output_rate) {
446 prev_sample1 = next_sample1;
447 next_sample1 = short(read_little_endian_short((char*)(in_buf++)));
448 prev_sample2 = next_sample2;
449 next_sample2 = short(read_little_endian_short((char*)(in_buf++)));
450 prev_time += output_rate;
451 }
452 write_little_endian_short((char*)out,
453 ((time-prev_time)*next_sample1 +
454 (input_rate-time+prev_time)*prev_sample1) / input_rate);
455 out++;
456 write_little_endian_short((char*)out,
457 ((time-prev_time)*next_sample2 +
458 (input_rate-time+prev_time)*prev_sample2) / input_rate);
459 *out++;
460 }
461 prev_time += output_rate; prev_time -= input_rate * outlen;
462 prev_sample1 = next_sample1; prev_sample2 = next_sample2;
463 if (first_flag == 1) {
464 outlen++; first_flag = 2;
465 }
466 memcpy(in_buf_orig, out_orig, outlen*2*sizeof(short));
467 return outlen;
468 }
469
470
471 /************************************************************:
472 **
473 ** MP3FILE stream reader
474 */
475
476 int WAVFILE::freq = 48000;
477 int WAVFILE::channels = 2;
478 int WAVFILE::format = MIX_DEFAULT_FORMAT;
479
480 #if HAVE_LIBMAD
481
482 #include<mad.h>
483 #define MPEG_BUFSZ 40000 /* 2.5 s at 128 kbps; 1 s at 320 kbps */
484 struct MP3FILE_impl {
485 enum { PREPARE, RUN, WRITE, DONE} status;
486 struct mad_decoder decoder;
487 char* data;
488 int data_len;
489 char* write_data;
490 unsigned int write_data_len;
491 unsigned int write_pointer;
492 unsigned int src_pointer;
493 FILE* stream;
494 MP3FILE_impl(FILE*);
495 ~MP3FILE_impl();
496 static enum mad_flow callback_read(void *data, struct mad_stream *stream);
497 static enum mad_flow callback_error(void *data, struct mad_stream *stream, struct mad_frame *frame);
498 static enum mad_flow callback_write(void *data, struct mad_header const *header, struct mad_pcm *pcm);
499 enum mad_flow callback_write_impl(struct mad_pcm *pcm);
500 void run(void);
501 };
502
503 MP3FILE_impl::MP3FILE_impl(FILE* _stream) {
504 stream = _stream;
505 data = new char[MPEG_BUFSZ];
506 data_len = 0;
507 src_pointer = 0;
508 write_data = 0;
509 write_data_len = 0;
510 write_pointer = 0;
511
512 /* initialize decoder */
513 mad_decoder_init(&decoder, (void*)this, callback_read, 0 /* header */, 0 /* filter */, callback_write,
514 callback_error, 0 /* message */);
515 /* prepare stream */
516 status = PREPARE;
517 *(void**)(&decoder.sync) = malloc(sizeof(*decoder.sync));
518
519 mad_stream_init(&decoder.sync->stream);
520 mad_frame_init(&decoder.sync->frame);
521 mad_synth_init(&decoder.sync->synth);
522
523 mad_stream_options(&decoder.sync->stream, decoder.options);
524
525 while(status != WRITE && status != DONE) run();
526 }
527 MP3FILE_impl::~MP3FILE_impl() {
528 free(decoder.sync);
529 mad_decoder_finish(&decoder);
530 delete[] data;
531 return;
532 }
533
534 void MP3FILE_impl::run(void) {
535 if (status == DONE) return;
536 struct mad_stream *stream = &decoder.sync->stream;
537 struct mad_frame *frame = &decoder.sync->frame;
538 struct mad_synth *synth = &decoder.sync->synth;
539 if (status == PREPARE) {
540 switch (decoder.input_func(decoder.cb_data, stream)) {
541 case MAD_FLOW_STOP:
542 case MAD_FLOW_BREAK:
543 goto done;
544 case MAD_FLOW_CONTINUE:
545 status = RUN;
546 case MAD_FLOW_IGNORE:
547 break;
548 }
549 return;
550 }
551 if (status == RUN) {
552 if (mad_frame_decode(frame, stream) == -1) {
553 if (!MAD_RECOVERABLE(stream->error)) {
554 status = PREPARE;
555 return;
556 }
557 switch (decoder.error_func((void*)this, stream, frame)) {
558 case MAD_FLOW_STOP:
559 case MAD_FLOW_BREAK:
560 goto done;
561 case MAD_FLOW_IGNORE:
562 status = PREPARE;
563 return;
564 case MAD_FLOW_CONTINUE:
565 default:
566 return;
567 }
568 }
569
570 mad_synth_frame(synth, frame);
571 src_pointer = 0;
572 status = WRITE;
573 return;
574 }
575 if (status == WRITE) {
576 switch (decoder.output_func(decoder.cb_data, &frame->header, &synth->pcm)) {
577 case MAD_FLOW_STOP:
578 case MAD_FLOW_BREAK:
579 goto done;
580 case MAD_FLOW_IGNORE:
581 return;
582 case MAD_FLOW_CONTINUE:
583 status = RUN;
584 break;
585 }
586 if (stream->error == MAD_ERROR_BUFLEN) {
587 stream->error = MAD_ERROR_NONE;
588 status = PREPARE;
589 }
590 return;
591 }
592 done:
593 status = DONE;
594 mad_synth_finish(&decoder.sync->synth);
595 mad_frame_finish(&decoder.sync->frame);
596 mad_stream_finish(&decoder.sync->stream);
597 return;
598 }
599
600 enum mad_flow MP3FILE_impl::callback_read(void *data, struct mad_stream *stream)
601 {
602 MP3FILE_impl* impl = (MP3FILE_impl*)data;
603 if (stream->next_frame) {
604 impl->data_len -= (char*)stream->next_frame - impl->data;
605 memmove(impl->data, (char*)stream->next_frame, impl->data_len);
606 } else {
607 impl->data_len = 0;
608 }
609 int count;
610 if (feof(impl->stream)) {
611 if (stream->next_frame && (char*)stream->next_frame - impl->data > 0) {
612 // There is under processing data
613 count = 0;
614 } else {
615 // all data were processed
616 return MAD_FLOW_STOP;
617 }
618 } else {
619 count = fread(impl->data + impl->data_len, 1, MPEG_BUFSZ-impl->data_len, impl->stream);
620 if (count <= 0) {
621 return MAD_FLOW_BREAK;
622 }
623 }
624 impl->data_len += count;
625 if (impl->data_len < MPEG_BUFSZ) {
626 memset(impl->data + impl->data_len, 0, MPEG_BUFSZ-impl->data_len);
627 }
628 mad_stream_buffer(stream, (unsigned char*)impl->data, impl->data_len);
629 return MAD_FLOW_CONTINUE;
630 }
631
632 enum mad_flow MP3FILE_impl::callback_error(void *data, struct mad_stream *stream, struct mad_frame *frame)
633 {
634 MP3FILE_impl* impl = (MP3FILE_impl*)data;
635 fprintf(stdout, "decoding error 0x%04x (%s) at byte offset %u\n",
636 stream->error, mad_stream_errorstr(stream),
637 ftell(impl->stream) - ((impl->data+impl->data_len)-(char*)stream->this_frame));
638 /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */
639 return MAD_FLOW_CONTINUE;
640 }
641 signed int scale(mad_fixed_t sample)
642 {
643 /* round */
644 sample += (1L << (MAD_F_FRACBITS - 16));
645
646 /* clip */
647 if (sample >= MAD_F_ONE)
648 sample = MAD_F_ONE - 1;
649 else if (sample < -MAD_F_ONE)
650 sample = -MAD_F_ONE;
651
652 /* quantize */
653 return sample >> (MAD_F_FRACBITS + 1 - 16);
654 }
655 enum mad_flow MP3FILE_impl::callback_write(void *data, struct mad_header const *header, struct mad_pcm *pcm)
656 {
657 MP3FILE_impl* pimpl = (MP3FILE_impl*)data;
658 return pimpl->callback_write_impl(pcm);
659 }
660 enum mad_flow MP3FILE_impl::callback_write_impl(struct mad_pcm *pcm)
661 {
662 if (write_data_len == 0) return MAD_FLOW_IGNORE;
663 mad_fixed_t const *left_ch = pcm->samples[0] + src_pointer;
664 mad_fixed_t const *right_ch = pcm->samples[1] + src_pointer;
665
666 unsigned int nchannels = pcm->channels;
667 unsigned int nsamples = pcm->length - src_pointer;
668 if (write_pointer + nsamples * nchannels * 2 > write_data_len) {
669 nsamples = (write_data_len - write_pointer) / nchannels / 2;
670 }
671 write_data_len &= ~(nchannels*2-1); /* write_data_len はあらかじめ丸めておく */
672 src_pointer += nsamples;
673 if (write_data == 0) { // skip data write
674 write_pointer += nsamples*2*2;
675 } else while(nsamples--) {
676 signed int sample = scale(*left_ch++);
677 write_data[write_pointer++] = sample & 0xff;
678 write_data[write_pointer++] = (sample>>8) & 0xff;
679 if (nchannels == 2) {
680 sample = scale(*right_ch++);
681 }
682 write_data[write_pointer++] = sample & 0xff;
683 write_data[write_pointer++] = (sample>>8) & 0xff;
684 }
685 if (write_pointer >= write_data_len) return MAD_FLOW_IGNORE;
686 else return MAD_FLOW_CONTINUE;
687 }
688
689 MP3FILE::MP3FILE(FILE* stream, int len) {
690 pimpl = new MP3FILE_impl(stream);
691 if (pimpl->status == MP3FILE_impl::DONE) {
692 delete pimpl;
693 pimpl = 0;
694 fclose(stream);
695 return;
696 }
697 wavinfo.SamplingRate = pimpl->decoder.sync->synth.pcm.samplerate;
698 wavinfo.Channels = 2;
699 wavinfo.DataBits = 16;
700 }
701 MP3FILE::~MP3FILE() {
702 if (pimpl) {
703 FILE* s = pimpl->stream;
704 delete pimpl;
705 fclose(s);
706 }
707 pimpl = 0;
708 }
709 int MP3FILE::Read(char* buf, int blksize, int blklen) {
710 if (pimpl == 0) return -1;
711 pimpl->write_data = buf;
712 pimpl->write_data_len = blksize*blklen;
713 pimpl->write_pointer = 0;
714 do {
715 pimpl->run();
716 } while(pimpl->status != MP3FILE_impl::DONE && pimpl->write_pointer < pimpl->write_data_len);
717 return pimpl->write_pointer / blksize;
718 }
719 void MP3FILE::Seek(int count) {
720 FILE* stream = pimpl->stream;
721 delete pimpl;
722 fseek(stream,0,0);
723 pimpl = new MP3FILE_impl(stream);
724 if (pimpl->status == MP3FILE_impl::DONE) {
725 delete pimpl;
726 pimpl = 0;
727 fclose(stream);
728 return;
729 }
730 int blksize = 1;
731 blksize *= wavinfo.Channels * (wavinfo.DataBits/8);
732 pimpl->write_data = 0;
733 pimpl->write_data_len = count * blksize;
734 pimpl->write_pointer = 0;
735 do {
736 pimpl->run();
737 } while(pimpl->status != MP3FILE_impl::DONE && pimpl->write_pointer < pimpl->write_data_len);
738 return;
739 }
740 #elif USE_SMPEG
741 #include<smpeg/smpeg.h>
742
743 struct MP3FILE_impl {
744 SMPEG* info;
745 FILE* stream;
746 MP3FILE_impl(FILE*);
747 };
748
749 MP3FILE_impl::MP3FILE_impl(FILE* _stream) {
750 stream = _stream;
751 info = SMPEG_new_descr(fileno(stream), NULL, 0);
752 fprintf(stderr,"mp3 %x\n",info);
753 if (info && SMPEG_error(info) ) info = 0;
754 SMPEG_enableaudio(info, 0);
755 SMPEG_enableaudio(info, 1);
756 SMPEG_play(info);
757 }
758
759 MP3FILE::MP3FILE(FILE* stream, int len) {
760 pimpl = new MP3FILE_impl(stream);
761 if (pimpl->info == 0) {
762 delete pimpl;
763 fclose(stream);
764 return;
765 }
766 SDL_AudioSpec fmt;
767 SMPEG_wantedSpec(pimpl->info, &fmt);
768 wavinfo.SamplingRate = fmt.freq;
769 wavinfo.Channels = fmt.channels;
770 wavinfo.DataBits = (fmt.format == AUDIO_S8) ? 8:16;
771 }
772 MP3FILE::~MP3FILE() {
773 if (pimpl && pimpl->info) {
774 if (SMPEG_status(pimpl->info) == SMPEG_PLAYING) SMPEG_stop(pimpl->info);
775 SMPEG_delete(pimpl->info);
776 }
777 if (pimpl) {
778 fclose(pimpl->stream);
779 delete pimpl;
780 pimpl = 0;
781 }
782 }
783 int MP3FILE::Read(char* buf, int blksize, int blklen) {
784 if (pimpl == 0 || pimpl->info == 0) return -1;
785 int r = SMPEG_playAudio(pimpl->info, (Uint8*)buf, blksize*blklen);
786 if (r <= 0) { // end of file
787 return -1;
788 }
789 return r / blksize;
790 }
791 void MP3FILE::Seek(int count) {
792 if (pimpl == 0 || pimpl->info == 0) return;
793 SMPEG_stop(pimpl->info);
794 SMPEG_rewind(pimpl->info);
795 SMPEG_play(pimpl->info);
796 count /= 4;
797 count *= 4; // reduce noise; possibly SMPEG error
798 char* d = new char[count*channels*2];
799 Read(d,count,channels*2);
800 delete[] d;
801 return;
802 }
803 #else /* SMPEG */
804 MP3FILE::MP3FILE(FILE* stream, int len) {pimpl = 0;}
805 MP3FILE::~MP3FILE(){}
806 void MP3FILE::Seek(int count){}
807 int MP3FILE::Read(char* buf, int blksize, int blklen){return -1;}
808 #endif /* SMPEG */