1 /*
2  MPEG decoder plugin for DeaDBeeF Player
3  Copyright (C) 2009-2014 Alexey Yakovenko
4 
5  This software is provided 'as-is', without any express or implied
6  warranty.  In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17 
18  2. Altered source versions must be plainly marked as such, and must not be
19  misrepresented as being the original software.
20 
21  3. This notice may not be removed or altered from any source distribution.
22  */
23 
24 #include <string.h>
25 #include "mp3_mad.h"
26 
27 //#define trace(...) { fprintf(stderr, __VA_ARGS__); }
28 #define trace(fmt,...)
29 
30 void
mp3_mad_init(mp3_info_t * info)31 mp3_mad_init (mp3_info_t *info) {
32     mad_stream_init(&info->mad_stream);
33     mad_stream_options (&info->mad_stream, MAD_OPTION_IGNORECRC);
34     mad_frame_init(&info->mad_frame);
35     mad_synth_init(&info->mad_synth);
36 }
37 
38 void
mp3_mad_free(mp3_info_t * info)39 mp3_mad_free (mp3_info_t *info) {
40     mad_synth_finish (&info->mad_synth);
41     mad_frame_finish (&info->mad_frame);
42     mad_stream_finish (&info->mad_stream);
43 }
44 
45 /****************************************************************************
46  * Converts a sample from libmad's fixed point number format to a signed	*
47  * short (16 bits).															*
48  ****************************************************************************/
49 static inline int16_t
MadFixedToSshort(mad_fixed_t Fixed)50 MadFixedToSshort(mad_fixed_t Fixed)
51 {
52     /* A fixed point number is formed of the following bit pattern:
53      *
54      * SWWWFFFFFFFFFFFFFFFFFFFFFFFFFFFF
55      * MSB                          LSB
56      * S ==> Sign (0 is positive, 1 is negative)
57      * W ==> Whole part bits
58      * F ==> Fractional part bits
59      *
60      * This pattern contains MAD_F_FRACBITS fractional bits, one
61      * should alway use this macro when working on the bits of a fixed
62      * point number. It is not guaranteed to be constant over the
63      * different platforms supported by libmad.
64      *
65      * The signed short value is formed, after clipping, by the least
66      * significant whole part bit, followed by the 15 most significant
67      * fractional part bits. Warning: this is a quick and dirty way to
68      * compute the 16-bit number, madplay includes much better
69      * algorithms.
70      */
71 
72     /* Clipping */
73     if(Fixed>=MAD_F_ONE)
74         return(32767);
75     if(Fixed<=-MAD_F_ONE)
76         return(-32768);
77 
78     /* Conversion. */
79     Fixed=Fixed>>(MAD_F_FRACBITS-15);
80     return((signed short)Fixed);
81 }
82 
83 static inline float
MadFixedToFloat(mad_fixed_t Fixed)84 MadFixedToFloat (mad_fixed_t Fixed) {
85     return (float)((Fixed) / (float)(1L << MAD_F_FRACBITS));
86 }
87 
88 #define MadErrorString(x) mad_stream_errorstr(x)
89 
90 void
mp3_mad_decode(mp3_info_t * info)91 mp3_mad_decode (mp3_info_t *info) {
92     // copy synthesized samples into readbuffer
93     int idx = info->mad_synth.pcm.length-info->buffer.decode_remaining;
94     // stereo
95     if (MAD_NCHANNELS(&info->mad_frame.header) == 2 && info->info.fmt.channels == 2) {
96         while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
97             *((int16_t*)info->buffer.out) = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
98             info->buffer.readsize -= 2;
99             info->buffer.out += 2;
100             *((int16_t*)info->buffer.out) = MadFixedToSshort (info->mad_synth.pcm.samples[1][idx]);
101             info->buffer.readsize -= 2;
102             info->buffer.out += 2;
103             info->buffer.decode_remaining--;
104             idx++;
105         }
106     }
107     // mono
108     else if (MAD_NCHANNELS(&info->mad_frame.header) == 1 && info->info.fmt.channels == 1){
109         while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
110             *((int16_t*)info->buffer.out) = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
111             info->buffer.readsize -= 2;
112             info->buffer.out += 2;
113             info->buffer.decode_remaining--;
114             idx++;
115         }
116     }
117     // workaround for bad mp3s that have both mono and stereo frames
118     else if (MAD_NCHANNELS(&info->mad_frame.header) == 1 && info->info.fmt.channels == 2) {
119         while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
120             int16_t sample = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
121             *((int16_t*)info->buffer.out) = sample;
122             info->buffer.readsize -= 2;
123             info->buffer.out += 2;
124             *((int16_t*)info->buffer.out) = sample;
125             info->buffer.readsize -= 2;
126             info->buffer.out += 2;
127             info->buffer.decode_remaining--;
128             idx++;
129         }
130     }
131     else if (MAD_NCHANNELS(&info->mad_frame.header) == 2 && info->info.fmt.channels == 1) {
132         while (info->buffer.decode_remaining > 0 && info->buffer.readsize > 0) {
133             int16_t sample = MadFixedToSshort (info->mad_synth.pcm.samples[0][idx]);
134             *((int16_t*)info->buffer.out) = sample;
135             info->buffer.readsize -= 2;
136             info->buffer.out += 2;
137             info->buffer.decode_remaining--;
138             idx++;
139         }
140     }
141 }
142 
143 int
mp3_mad_stream_frame(mp3_info_t * info)144 mp3_mad_stream_frame (mp3_info_t *info) {
145     int eof = 0;
146     while (!eof && (info->mad_stream.buffer == NULL || info->buffer.decode_remaining <= 0)) {
147         // read more MPEG data if needed
148         if(info->mad_stream.buffer==NULL || info->mad_stream.error==MAD_ERROR_BUFLEN) {
149             // copy part of last frame to beginning
150             if (info->mad_stream.next_frame && info->mad_stream.bufend <= info->mad_stream.next_frame) {
151                 eof = 1;
152                 break;
153             }
154             if (info->mad_stream.next_frame != NULL) {
155                 info->buffer.remaining = info->mad_stream.bufend - info->mad_stream.next_frame;
156                 memmove (info->buffer.input, info->mad_stream.next_frame, info->buffer.remaining);
157             }
158             int size = READBUFFER - info->buffer.remaining;
159             int bytesread = 0;
160             uint8_t *bytes = info->buffer.input + info->buffer.remaining;
161             bytesread = deadbeef->fread (bytes, 1, size, info->buffer.file);
162             if (!bytesread) {
163                 // add guard
164                 eof = 1;
165                 memset (bytes, 0, 8);
166                 bytesread = 8;
167             }
168             if (bytesread < size) {
169                 // end of file
170                 size -= bytesread;
171                 bytes += bytesread;
172             }
173             bytesread += info->buffer.remaining;
174             mad_stream_buffer(&info->mad_stream,info->buffer.input,bytesread);
175             if (info->mad_stream.buffer==NULL) {
176                 // check sync bits
177                 if (bytes[0] != 0xff || (bytes[1]&(3<<5)) != (3<<5)) {
178                     trace ("mp3: read didn't start at frame boundary!\ncmp3_scan_stream is broken\n");
179                 }
180                 else {
181                     trace ("mp3: streambuffer=NULL\n");
182                 }
183             }
184         }
185         info->mad_stream.error=0;
186 
187         // decode next frame
188         if(mad_frame_decode(&info->mad_frame, &info->mad_stream))
189         {
190             if(MAD_RECOVERABLE(info->mad_stream.error))
191             {
192                 if(info->mad_stream.error!=MAD_ERROR_LOSTSYNC) {
193                     //                    printf ("mp3: recoverable frame level error (%s)\n", MadErrorString(&info->stream));
194                 }
195                 if (info->buffer.lead_in_frames > 0) {
196                     info->buffer.lead_in_frames--;
197                 }
198                 continue;
199             }
200             else {
201                 if(info->mad_stream.error==MAD_ERROR_BUFLEN) {
202                     //                    printf ("mp3: recoverable frame level error (%s)\n", MadErrorString(&info->stream));
203                     continue;
204                 }
205                 else
206                 {
207                     //                    printf ("mp3: unrecoverable frame level error (%s).\n", MadErrorString(&info->stream));
208                     return -1; // fatal error
209                 }
210             }
211         }
212         mad_synth_frame(&info->mad_synth,&info->mad_frame);
213         if (info->buffer.lead_in_frames > 0) {
214             info->buffer.lead_in_frames--;
215             info->buffer.decode_remaining = 0;
216             continue;
217         }
218 
219         info->info.fmt.samplerate = info->mad_frame.header.samplerate;
220 
221         // synthesize single frame
222         info->buffer.decode_remaining = info->mad_synth.pcm.length;
223         deadbeef->streamer_set_bitrate (info->mad_frame.header.bitrate/1000);
224         break;
225     }
226 
227     return eof;
228 }
229 
230 mp3_decoder_api_t mad_api = {
231     .init = mp3_mad_init,
232     .free = mp3_mad_free,
233     .decode = mp3_mad_decode,
234     .stream_frame = mp3_mad_stream_frame,
235 };
236