Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2005 Dave Chapman |
| 11 | * |
| 12 | * All files in this archive are subject to the GNU General Public License. |
| 13 | * See the file COPYING in the source tree root for full license agreement. |
| 14 | * |
| 15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 16 | * KIND, either express or implied. |
| 17 | * |
| 18 | ****************************************************************************/ |
| 19 | |
Thom Johansen | c91e0bb | 2005-10-13 11:32:52 +0000 | [diff] [blame] | 20 | #include "codeclib.h" |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 21 | #include <codecs/libmad/mad.h> |
Magnus Holmgren | 753a897 | 2005-08-16 18:26:41 +0000 | [diff] [blame] | 22 | #include <inttypes.h> |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 23 | |
Jens Arnold | b8749fd | 2006-01-18 00:05:14 +0000 | [diff] [blame] | 24 | CODEC_HEADER |
| 25 | |
Thom Johansen | e602138 | 2005-10-27 11:32:02 +0000 | [diff] [blame] | 26 | struct mad_stream stream IBSS_ATTR; |
| 27 | struct mad_frame frame IBSS_ATTR; |
| 28 | struct mad_synth synth IBSS_ATTR; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 29 | |
| 30 | /* The following function is used inside libmad - let's hope it's never |
| 31 | called. |
| 32 | */ |
| 33 | |
| 34 | void abort(void) { |
| 35 | } |
| 36 | |
Thom Johansen | 10426db | 2005-06-22 21:18:05 +0000 | [diff] [blame] | 37 | #define INPUT_CHUNK_SIZE 8192 |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 38 | |
Thom Johansen | e602138 | 2005-10-27 11:32:02 +0000 | [diff] [blame] | 39 | mad_fixed_t mad_frame_overlap[2][32][18] IBSS_ATTR; |
| 40 | unsigned char mad_main_data[MAD_BUFFER_MDLEN] IBSS_ATTR; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 41 | /* TODO: what latency does layer 1 have? */ |
| 42 | int mpeg_latency[3] = { 0, 481, 529 }; |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 43 | |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 44 | #ifdef USE_IRAM |
| 45 | extern char iramcopy[]; |
| 46 | extern char iramstart[]; |
| 47 | extern char iramend[]; |
Jens Arnold | 07c4254 | 2006-01-08 22:50:14 +0000 | [diff] [blame] | 48 | extern char iedata[]; |
| 49 | extern char iend[]; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 50 | #endif |
| 51 | |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 52 | struct codec_api *ci; |
Magnus Holmgren | 753a897 | 2005-08-16 18:26:41 +0000 | [diff] [blame] | 53 | int64_t samplecount; |
| 54 | int64_t samplesdone; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 55 | int stop_skip, start_skip; |
| 56 | int current_stereo_mode = -1; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 57 | unsigned int current_frequency = 0; |
| 58 | |
| 59 | void recalc_samplecount(void) |
| 60 | { |
| 61 | /* NOTE: currently this doesn't work, the below calculated samples_count |
| 62 | seems to be right, but sometimes we just don't have all the data we |
| 63 | need... */ |
| 64 | if (ci->id3->frame_count) { |
| 65 | /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3, |
| 66 | it's probably not correct at all for MPEG2 and layer 1 */ |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 67 | samplecount = ((int64_t)ci->id3->frame_count) * 1152; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 68 | } else { |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 69 | samplecount = ((int64_t)ci->id3->length) * current_frequency / 1000; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 70 | } |
Magnus Holmgren | 753a897 | 2005-08-16 18:26:41 +0000 | [diff] [blame] | 71 | |
| 72 | samplecount -= start_skip + stop_skip; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 73 | } |
| 74 | |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 75 | /* this is the codec entry point */ |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 76 | enum codec_status codec_start(struct codec_api *api) |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 77 | { |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 78 | int status = CODEC_OK; |
Thom Johansen | 4d7e5df | 2005-10-13 12:15:31 +0000 | [diff] [blame] | 79 | long size; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 80 | int file_end; |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 81 | int frame_skip; /* samples to skip current frame */ |
| 82 | int samples_to_skip; /* samples to skip in total for this file (at start) */ |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 83 | char *inputbuffer; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 84 | |
| 85 | ci = api; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 86 | |
| 87 | #ifdef USE_IRAM |
Thom Johansen | 10426db | 2005-06-22 21:18:05 +0000 | [diff] [blame] | 88 | ci->memcpy(iramstart, iramcopy, iramend - iramstart); |
Jens Arnold | 07c4254 | 2006-01-08 22:50:14 +0000 | [diff] [blame] | 89 | ci->memset(iedata, 0, iend - iedata); |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 90 | #endif |
| 91 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 92 | if (codec_init(api)) |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 93 | return CODEC_ERROR; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 94 | |
| 95 | /* Create a decoder instance */ |
| 96 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 97 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); |
| 98 | ci->configure(DSP_DITHER, (bool *)false); |
Thom Johansen | a8b9fd1 | 2005-11-02 19:15:25 +0000 | [diff] [blame] | 99 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(MAD_F_FRACBITS)); |
Miika Pekkarinen | d8cb703 | 2005-06-26 19:41:29 +0000 | [diff] [blame] | 100 | ci->configure(DSP_SET_CLIP_MIN, (int *)-MAD_F_ONE); |
| 101 | ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1)); |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 102 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); |
Miika Pekkarinen | d8cb703 | 2005-06-26 19:41:29 +0000 | [diff] [blame] | 103 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 104 | ci->memset(&stream, 0, sizeof(struct mad_stream)); |
| 105 | ci->memset(&frame, 0, sizeof(struct mad_frame)); |
| 106 | ci->memset(&synth, 0, sizeof(struct mad_synth)); |
Miika Pekkarinen | 6b807b2 | 2005-07-30 13:46:38 +0000 | [diff] [blame] | 107 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 108 | mad_stream_init(&stream); |
| 109 | mad_frame_init(&frame); |
| 110 | mad_synth_init(&synth); |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 111 | |
| 112 | /* We do this so libmad doesn't try to call codec_calloc() */ |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 113 | ci->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 114 | frame.overlap = &mad_frame_overlap; |
| 115 | stream.main_data = &mad_main_data; |
| 116 | |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 117 | /* This label might need to be moved above all the init code, but I don't |
| 118 | think reiniting the codec is necessary for MPEG. It might even be unwanted |
| 119 | for gapless playback */ |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 120 | next_track: |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 121 | file_end = 0; |
Miika Pekkarinen | 0d63cbb | 2005-07-10 20:37:36 +0000 | [diff] [blame] | 122 | while (!*ci->taginfo_ready && !ci->stop_codec) |
Miika Pekkarinen | fbd4088 | 2005-07-11 18:47:47 +0000 | [diff] [blame] | 123 | ci->sleep(1); |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 124 | |
Miika Pekkarinen | d8cb703 | 2005-06-26 19:41:29 +0000 | [diff] [blame] | 125 | ci->configure(DSP_SET_FREQUENCY, (int *)ci->id3->frequency); |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 126 | current_frequency = ci->id3->frequency; |
Magnus Holmgren | 988ea2c | 2005-07-27 11:54:33 +0000 | [diff] [blame] | 127 | codec_set_replaygain(ci->id3); |
Miika Pekkarinen | d8cb703 | 2005-06-26 19:41:29 +0000 | [diff] [blame] | 128 | |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 129 | ci->request_buffer(&size, ci->id3->first_frame_offset); |
| 130 | ci->advance_buffer(size); |
Miika Pekkarinen | 5c2c991 | 2005-07-05 19:55:40 +0000 | [diff] [blame] | 131 | |
| 132 | if (ci->id3->lead_trim >= 0 && ci->id3->tail_trim >= 0) { |
| 133 | stop_skip = ci->id3->tail_trim - mpeg_latency[ci->id3->layer]; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 134 | if (stop_skip < 0) stop_skip = 0; |
Miika Pekkarinen | 5c2c991 | 2005-07-05 19:55:40 +0000 | [diff] [blame] | 135 | start_skip = ci->id3->lead_trim + mpeg_latency[ci->id3->layer]; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 136 | } else { |
| 137 | stop_skip = 0; |
| 138 | /* We want to skip this amount anyway */ |
Miika Pekkarinen | 5c2c991 | 2005-07-05 19:55:40 +0000 | [diff] [blame] | 139 | start_skip = mpeg_latency[ci->id3->layer]; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 140 | } |
Magnus Holmgren | 988ea2c | 2005-07-27 11:54:33 +0000 | [diff] [blame] | 141 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 142 | samplesdone = ((int64_t)ci->id3->elapsed) * current_frequency / 1000; |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 143 | samples_to_skip = start_skip; |
Magnus Holmgren | 15e0aeb | 2005-08-13 08:02:38 +0000 | [diff] [blame] | 144 | recalc_samplecount(); |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 145 | |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 146 | /* This is the decoding loop. */ |
| 147 | while (1) { |
Magnus Holmgren | 15e0aeb | 2005-08-13 08:02:38 +0000 | [diff] [blame] | 148 | int framelength; |
| 149 | |
Thom Johansen | 10426db | 2005-06-22 21:18:05 +0000 | [diff] [blame] | 150 | ci->yield(); |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 151 | if (ci->stop_codec || ci->reload_codec) |
| 152 | break; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 153 | |
| 154 | if (ci->seek_time) { |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 155 | int newpos; |
| 156 | |
Magnus Holmgren | 753a897 | 2005-08-16 18:26:41 +0000 | [diff] [blame] | 157 | samplesdone = ((int64_t) (ci->seek_time - 1)) |
| 158 | * current_frequency / 1000; |
Linus Nielsen Feltzing | 984712f | 2005-08-23 12:52:59 +0000 | [diff] [blame] | 159 | newpos = ci->mp3_get_filepos(ci->seek_time-1) + |
| 160 | ci->id3->first_frame_offset; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 161 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 162 | if (!ci->seek_buffer(newpos)) |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 163 | goto next_track; |
Miika Pekkarinen | 8a7d104 | 2005-08-21 18:12:31 +0000 | [diff] [blame] | 164 | if (newpos == 0) |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 165 | samples_to_skip = start_skip; |
Miika Pekkarinen | 8a7d104 | 2005-08-21 18:12:31 +0000 | [diff] [blame] | 166 | ci->seek_complete(); |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | /* Lock buffers */ |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 170 | if (stream.error == 0) { |
| 171 | inputbuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE); |
| 172 | if (size == 0 || inputbuffer == NULL) |
| 173 | break; |
Daniel Stenberg | 76667e2 | 2005-12-02 08:42:48 +0000 | [diff] [blame] | 174 | mad_stream_buffer(&stream, (unsigned char *)inputbuffer, size); |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 175 | } |
| 176 | |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 177 | if (mad_frame_decode(&frame, &stream)) { |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 178 | if (stream.error == MAD_FLAG_INCOMPLETE |
| 179 | || stream.error == MAD_ERROR_BUFLEN) { |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 180 | /* This makes the codec support partially corrupted files */ |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 181 | if (file_end == 30) |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 182 | break; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 183 | |
| 184 | /* Fill the buffer */ |
Magnus Holmgren | 0dac8b7 | 2005-12-22 21:53:21 +0000 | [diff] [blame] | 185 | if (stream.next_frame) |
| 186 | ci->advance_buffer_loc((void *)stream.next_frame); |
| 187 | else |
| 188 | ci->advance_buffer(size); |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 189 | stream.error = 0; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 190 | file_end++; |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 191 | continue; |
| 192 | } else if (MAD_RECOVERABLE(stream.error)) { |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 193 | continue; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 194 | } else { |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 195 | /* Some other unrecoverable error */ |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 196 | status = CODEC_ERROR; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 197 | break; |
| 198 | } |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 199 | break; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 200 | } |
Miika Pekkarinen | 3eb962d | 2005-07-07 07:15:05 +0000 | [diff] [blame] | 201 | |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 202 | file_end = 0; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 203 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 204 | mad_synth_frame(&synth, &frame); |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 205 | |
| 206 | /* We need to skip samples_to_skip samples from the start of every file |
| 207 | to properly support LAME style gapless MP3 files. samples_to_skip |
| 208 | might be larger than one frame. */ |
| 209 | if (samples_to_skip < synth.pcm.length) { |
| 210 | /* skip just part of the frame */ |
| 211 | frame_skip = samples_to_skip; |
| 212 | samples_to_skip = 0; |
| 213 | } else { |
| 214 | /* we need to skip an entire frame */ |
| 215 | frame_skip = synth.pcm.length; |
| 216 | samples_to_skip -= synth.pcm.length; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 217 | } |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 218 | |
| 219 | framelength = synth.pcm.length - frame_skip; |
Linus Nielsen Feltzing | 0da0534 | 2005-08-10 22:59:06 +0000 | [diff] [blame] | 220 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 221 | if (stop_skip > 0) { |
Magnus Holmgren | 753a897 | 2005-08-16 18:26:41 +0000 | [diff] [blame] | 222 | int64_t max = samplecount - samplesdone; |
Magnus Holmgren | 15e0aeb | 2005-08-13 08:02:38 +0000 | [diff] [blame] | 223 | |
| 224 | if (max < 0) max = 0; |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 225 | if (max < framelength) framelength = (int)max; |
Magnus Holmgren | 9758911 | 2005-12-01 21:09:09 +0000 | [diff] [blame] | 226 | if (framelength == 0 && frame_skip == 0) break; |
Magnus Holmgren | 15e0aeb | 2005-08-13 08:02:38 +0000 | [diff] [blame] | 227 | } |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 228 | |
| 229 | /* Check if sample rate and stereo settings changed in this frame. */ |
| 230 | if (frame.header.samplerate != current_frequency) { |
| 231 | current_frequency = frame.header.samplerate; |
| 232 | ci->configure(DSP_SWITCH_FREQUENCY, (int *)current_frequency); |
| 233 | recalc_samplecount(); |
| 234 | } |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 235 | if (MAD_NCHANNELS(&frame.header) == 2) { |
Miika Pekkarinen | d54811f | 2005-07-02 16:52:30 +0000 | [diff] [blame] | 236 | if (current_stereo_mode != STEREO_NONINTERLEAVED) { |
| 237 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); |
| 238 | current_stereo_mode = STEREO_NONINTERLEAVED; |
| 239 | } |
Miika Pekkarinen | d54811f | 2005-07-02 16:52:30 +0000 | [diff] [blame] | 240 | } else { |
| 241 | if (current_stereo_mode != STEREO_MONO) { |
| 242 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO); |
| 243 | current_stereo_mode = STEREO_MONO; |
| 244 | } |
Miika Pekkarinen | d54811f | 2005-07-02 16:52:30 +0000 | [diff] [blame] | 245 | } |
Thom Johansen | 6b8bd6b | 2005-11-02 19:02:25 +0000 | [diff] [blame] | 246 | |
| 247 | /* Check if we can just skip the entire frame. */ |
| 248 | if (frame_skip < synth.pcm.length) { |
| 249 | /* In case of a mono file, the second array will be ignored. */ |
| 250 | ci->pcmbuf_insert_split(&synth.pcm.samples[0][frame_skip], |
| 251 | &synth.pcm.samples[1][frame_skip], |
| 252 | framelength * 4); |
| 253 | } |
Miika Pekkarinen | d8cb703 | 2005-06-26 19:41:29 +0000 | [diff] [blame] | 254 | |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 255 | if (stream.next_frame) |
| 256 | ci->advance_buffer_loc((void *)stream.next_frame); |
Miika Pekkarinen | 3eb962d | 2005-07-07 07:15:05 +0000 | [diff] [blame] | 257 | else |
| 258 | ci->advance_buffer(size); |
Magnus Holmgren | 15e0aeb | 2005-08-13 08:02:38 +0000 | [diff] [blame] | 259 | |
| 260 | samplesdone += framelength; |
Magnus Holmgren | 753a897 | 2005-08-16 18:26:41 +0000 | [diff] [blame] | 261 | ci->set_elapsed(samplesdone / (current_frequency / 1000)); |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 262 | } |
Thom Johansen | 0059995 | 2005-10-12 16:25:59 +0000 | [diff] [blame] | 263 | stream.error = 0; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 264 | |
| 265 | if (ci->request_next_track()) |
| 266 | goto next_track; |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 267 | |
| 268 | return status; |
Daniel Stenberg | 1dd672f | 2005-06-22 19:41:30 +0000 | [diff] [blame] | 269 | } |