root/music2/wavfile.cc

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