MP3 Player. You can change fwd/rev speed and skip. see: http://mbed.org/users/okini3939/notebook/lpc4088_madplayer/
Dependencies: I2SSlave SDFileSystem TLV320 mbed
player.cpp@0:8ba6230eefbd, 2014-02-18 (annotated)
- Committer:
- okini3939
- Date:
- Tue Feb 18 00:22:50 2014 +0000
- Revision:
- 0:8ba6230eefbd
1st build
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
okini3939 | 0:8ba6230eefbd | 1 | #include "mbed.h" |
okini3939 | 0:8ba6230eefbd | 2 | #include "player.h" |
okini3939 | 0:8ba6230eefbd | 3 | #include "SDFileSystem.h" |
okini3939 | 0:8ba6230eefbd | 4 | #include "sdram.h" |
okini3939 | 0:8ba6230eefbd | 5 | |
okini3939 | 0:8ba6230eefbd | 6 | #define DACBUF_SIZE (1024 * 1024 * 8 - 1024) |
okini3939 | 0:8ba6230eefbd | 7 | SDFileSystem sd(p5, p6, p7, p8, "sd"); |
okini3939 | 0:8ba6230eefbd | 8 | TLV320 audio(p32, p31, 0x34, p11, p12, p13, p14, p16); // I2S Codec / sda, scl, addr, tx_sda, tx_ws, clk, rx_sda, rx_ws |
okini3939 | 0:8ba6230eefbd | 9 | |
okini3939 | 0:8ba6230eefbd | 10 | static struct mad_decoder decoder; |
okini3939 | 0:8ba6230eefbd | 11 | struct dacout_s *dacbuf; |
okini3939 | 0:8ba6230eefbd | 12 | volatile int dac_r, dac_w, dac_l; |
okini3939 | 0:8ba6230eefbd | 13 | FILE *fp; |
okini3939 | 0:8ba6230eefbd | 14 | volatile int player_busy = 0, cmd_stop = 0; |
okini3939 | 0:8ba6230eefbd | 15 | int dac_step = 1, dac_vol = 100; |
okini3939 | 0:8ba6230eefbd | 16 | |
okini3939 | 0:8ba6230eefbd | 17 | extern DigitalOut led1, led2, led3, led4; |
okini3939 | 0:8ba6230eefbd | 18 | extern Serial pc; |
okini3939 | 0:8ba6230eefbd | 19 | |
okini3939 | 0:8ba6230eefbd | 20 | |
okini3939 | 0:8ba6230eefbd | 21 | bool isFull() { |
okini3939 | 0:8ba6230eefbd | 22 | return (((dac_w + 1) % DACBUF_SIZE) == dac_r); |
okini3939 | 0:8ba6230eefbd | 23 | }; |
okini3939 | 0:8ba6230eefbd | 24 | bool isEmpty() { |
okini3939 | 0:8ba6230eefbd | 25 | return (dac_r == dac_w); |
okini3939 | 0:8ba6230eefbd | 26 | }; |
okini3939 | 0:8ba6230eefbd | 27 | bool isEmpty2() { |
okini3939 | 0:8ba6230eefbd | 28 | return (dac_r == dac_l); |
okini3939 | 0:8ba6230eefbd | 29 | }; |
okini3939 | 0:8ba6230eefbd | 30 | uint32_t available() { |
okini3939 | 0:8ba6230eefbd | 31 | return (dac_w >= dac_r) ? dac_w - dac_r : DACBUF_SIZE - dac_r + dac_w; |
okini3939 | 0:8ba6230eefbd | 32 | }; |
okini3939 | 0:8ba6230eefbd | 33 | uint32_t available2() { |
okini3939 | 0:8ba6230eefbd | 34 | return (dac_r >= dac_l) ? dac_r - dac_l : DACBUF_SIZE - dac_l + dac_r; |
okini3939 | 0:8ba6230eefbd | 35 | }; |
okini3939 | 0:8ba6230eefbd | 36 | |
okini3939 | 0:8ba6230eefbd | 37 | |
okini3939 | 0:8ba6230eefbd | 38 | void isr_audio () |
okini3939 | 0:8ba6230eefbd | 39 | { |
okini3939 | 0:8ba6230eefbd | 40 | int i, j, a; |
okini3939 | 0:8ba6230eefbd | 41 | static int buf[4] = {0,0,0,0}; |
okini3939 | 0:8ba6230eefbd | 42 | static int w = 0; |
okini3939 | 0:8ba6230eefbd | 43 | static short l = 0, r = 0; |
okini3939 | 0:8ba6230eefbd | 44 | |
okini3939 | 0:8ba6230eefbd | 45 | for (i = 0; i < 4; i ++) { |
okini3939 | 0:8ba6230eefbd | 46 | if (dac_step > 0 && !isEmpty()) { |
okini3939 | 0:8ba6230eefbd | 47 | // fwd |
okini3939 | 0:8ba6230eefbd | 48 | for (j = 0; j < dac_step; j ++) { |
okini3939 | 0:8ba6230eefbd | 49 | // buf[i] = (dacbuf[dac_r].l << 16) | dacbuf[dac_r].r; |
okini3939 | 0:8ba6230eefbd | 50 | l = dacbuf[dac_r].l; |
okini3939 | 0:8ba6230eefbd | 51 | r = dacbuf[dac_r].r; |
okini3939 | 0:8ba6230eefbd | 52 | buf[i] = (l << 16) | (r & 0xffff); |
okini3939 | 0:8ba6230eefbd | 53 | dac_r = (dac_r + 1) % DACBUF_SIZE; |
okini3939 | 0:8ba6230eefbd | 54 | if (isEmpty()) break; |
okini3939 | 0:8ba6230eefbd | 55 | } |
okini3939 | 0:8ba6230eefbd | 56 | } else |
okini3939 | 0:8ba6230eefbd | 57 | if (dac_step < 0 && !isEmpty2()) { |
okini3939 | 0:8ba6230eefbd | 58 | // rev |
okini3939 | 0:8ba6230eefbd | 59 | for (j = 0; j < -dac_step; j ++) { |
okini3939 | 0:8ba6230eefbd | 60 | // buf[i] = (dacbuf[dac_r].l << 16) | dacbuf[dac_r].r; |
okini3939 | 0:8ba6230eefbd | 61 | l = dacbuf[dac_r].l; |
okini3939 | 0:8ba6230eefbd | 62 | r = dacbuf[dac_r].r; |
okini3939 | 0:8ba6230eefbd | 63 | buf[i] = (l << 16) | (r & 0xffff); |
okini3939 | 0:8ba6230eefbd | 64 | dac_r = (dac_r - 1 + DACBUF_SIZE) % DACBUF_SIZE; |
okini3939 | 0:8ba6230eefbd | 65 | if (isEmpty2()) break; |
okini3939 | 0:8ba6230eefbd | 66 | } |
okini3939 | 0:8ba6230eefbd | 67 | } else { |
okini3939 | 0:8ba6230eefbd | 68 | // under flow |
okini3939 | 0:8ba6230eefbd | 69 | if (l > 0) l --; |
okini3939 | 0:8ba6230eefbd | 70 | if (l < 0) l ++; |
okini3939 | 0:8ba6230eefbd | 71 | if (r > 0) r --; |
okini3939 | 0:8ba6230eefbd | 72 | if (r < 0) r ++; |
okini3939 | 0:8ba6230eefbd | 73 | buf[i] = (l << 16) | (r & 0xffff); |
okini3939 | 0:8ba6230eefbd | 74 | } |
okini3939 | 0:8ba6230eefbd | 75 | } |
okini3939 | 0:8ba6230eefbd | 76 | audio.write(buf, 0, 4); |
okini3939 | 0:8ba6230eefbd | 77 | } |
okini3939 | 0:8ba6230eefbd | 78 | |
okini3939 | 0:8ba6230eefbd | 79 | int init_audio () { |
okini3939 | 0:8ba6230eefbd | 80 | if (sdram_init() == 1) { |
okini3939 | 0:8ba6230eefbd | 81 | pc.printf("Failed to initialize SDRAM\n"); |
okini3939 | 0:8ba6230eefbd | 82 | return -1; |
okini3939 | 0:8ba6230eefbd | 83 | } |
okini3939 | 0:8ba6230eefbd | 84 | malloc(16); |
okini3939 | 0:8ba6230eefbd | 85 | dacbuf = (dacout_s*)malloc(sizeof(dacout_s) * DACBUF_SIZE); |
okini3939 | 0:8ba6230eefbd | 86 | if (dacbuf == NULL) return -1; |
okini3939 | 0:8ba6230eefbd | 87 | pc.printf("memory %08x\r\n", dacbuf); |
okini3939 | 0:8ba6230eefbd | 88 | |
okini3939 | 0:8ba6230eefbd | 89 | audio.power(0x02); // mic off |
okini3939 | 0:8ba6230eefbd | 90 | audio.inputVolume(0, 0); |
okini3939 | 0:8ba6230eefbd | 91 | audio.frequency(44100); |
okini3939 | 0:8ba6230eefbd | 92 | audio.attach(&isr_audio); |
okini3939 | 0:8ba6230eefbd | 93 | audio.start(TRANSMIT); |
okini3939 | 0:8ba6230eefbd | 94 | NVIC_SetPriority(I2S_IRQn, 1); |
okini3939 | 0:8ba6230eefbd | 95 | NVIC_SetPriority(TIMER3_IRQn, 10); |
okini3939 | 0:8ba6230eefbd | 96 | return 0; |
okini3939 | 0:8ba6230eefbd | 97 | } |
okini3939 | 0:8ba6230eefbd | 98 | |
okini3939 | 0:8ba6230eefbd | 99 | int play (char *filename) { |
okini3939 | 0:8ba6230eefbd | 100 | int i; |
okini3939 | 0:8ba6230eefbd | 101 | |
okini3939 | 0:8ba6230eefbd | 102 | DBG("play: %s\r\n", filename); |
okini3939 | 0:8ba6230eefbd | 103 | fp = fopen(filename, "rb"); |
okini3939 | 0:8ba6230eefbd | 104 | if(!fp) { |
okini3939 | 0:8ba6230eefbd | 105 | pc.printf("file error\r\n"); |
okini3939 | 0:8ba6230eefbd | 106 | return -1; |
okini3939 | 0:8ba6230eefbd | 107 | } |
okini3939 | 0:8ba6230eefbd | 108 | player_busy = 1; |
okini3939 | 0:8ba6230eefbd | 109 | dac_r = dac_w = dac_l = 0; |
okini3939 | 0:8ba6230eefbd | 110 | dac_step = 1; |
okini3939 | 0:8ba6230eefbd | 111 | cmd_stop = 0; |
okini3939 | 0:8ba6230eefbd | 112 | led2 = 0; |
okini3939 | 0:8ba6230eefbd | 113 | mad_decoder_init(&decoder, NULL, input, 0, 0, output, error_fn, 0); |
okini3939 | 0:8ba6230eefbd | 114 | mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); |
okini3939 | 0:8ba6230eefbd | 115 | mad_decoder_finish(&decoder); |
okini3939 | 0:8ba6230eefbd | 116 | fclose(fp); |
okini3939 | 0:8ba6230eefbd | 117 | fp = 0; |
okini3939 | 0:8ba6230eefbd | 118 | dac_r = dac_w = 0; |
okini3939 | 0:8ba6230eefbd | 119 | led2 = 1; |
okini3939 | 0:8ba6230eefbd | 120 | player_busy = 0; |
okini3939 | 0:8ba6230eefbd | 121 | wait_ms(100); |
okini3939 | 0:8ba6230eefbd | 122 | DBG("eof\r\n"); |
okini3939 | 0:8ba6230eefbd | 123 | return 0; |
okini3939 | 0:8ba6230eefbd | 124 | } |
okini3939 | 0:8ba6230eefbd | 125 | |
okini3939 | 0:8ba6230eefbd | 126 | int command (char *cmd) { |
okini3939 | 0:8ba6230eefbd | 127 | int i, r = -1; |
okini3939 | 0:8ba6230eefbd | 128 | |
okini3939 | 0:8ba6230eefbd | 129 | pc.printf("command %s\r\n", cmd); |
okini3939 | 0:8ba6230eefbd | 130 | switch (cmd[0]) { |
okini3939 | 0:8ba6230eefbd | 131 | case 'P': |
okini3939 | 0:8ba6230eefbd | 132 | if (!player_busy) { |
okini3939 | 0:8ba6230eefbd | 133 | char buf[40]; |
okini3939 | 0:8ba6230eefbd | 134 | strcpy(buf, "/sd/"); |
okini3939 | 0:8ba6230eefbd | 135 | strcat(buf, &cmd[1]); |
okini3939 | 0:8ba6230eefbd | 136 | r = play(buf); |
okini3939 | 0:8ba6230eefbd | 137 | } |
okini3939 | 0:8ba6230eefbd | 138 | break; |
okini3939 | 0:8ba6230eefbd | 139 | case 'S': |
okini3939 | 0:8ba6230eefbd | 140 | cmd_stop = 1; |
okini3939 | 0:8ba6230eefbd | 141 | r = 0; |
okini3939 | 0:8ba6230eefbd | 142 | break; |
okini3939 | 0:8ba6230eefbd | 143 | case 'T': |
okini3939 | 0:8ba6230eefbd | 144 | i = atoi(&cmd[1]); |
okini3939 | 0:8ba6230eefbd | 145 | if (i < -10 || i > 10) break; |
okini3939 | 0:8ba6230eefbd | 146 | dac_step = i; |
okini3939 | 0:8ba6230eefbd | 147 | DBG("dac_step %d\r\n", dac_step); |
okini3939 | 0:8ba6230eefbd | 148 | r = 0; |
okini3939 | 0:8ba6230eefbd | 149 | break; |
okini3939 | 0:8ba6230eefbd | 150 | case 'Q': |
okini3939 | 0:8ba6230eefbd | 151 | if (cmd[1] == '+' || cmd[1] == '-') { |
okini3939 | 0:8ba6230eefbd | 152 | i = atof(&cmd[1]) * 44100; |
okini3939 | 0:8ba6230eefbd | 153 | if (i < 0 && i < - available2()) break; |
okini3939 | 0:8ba6230eefbd | 154 | if (i > 0 && i > available()) break; |
okini3939 | 0:8ba6230eefbd | 155 | dac_r += i; |
okini3939 | 0:8ba6230eefbd | 156 | DBG("skip %+d\r\n", i); |
okini3939 | 0:8ba6230eefbd | 157 | } else { |
okini3939 | 0:8ba6230eefbd | 158 | i = atof(&cmd[1]) * 44100; |
okini3939 | 0:8ba6230eefbd | 159 | if (i < dac_l || i > dac_r + available()) break; |
okini3939 | 0:8ba6230eefbd | 160 | dac_r = i; |
okini3939 | 0:8ba6230eefbd | 161 | DBG("skip %d\r\n", i); |
okini3939 | 0:8ba6230eefbd | 162 | } |
okini3939 | 0:8ba6230eefbd | 163 | r = 0; |
okini3939 | 0:8ba6230eefbd | 164 | break; |
okini3939 | 0:8ba6230eefbd | 165 | case 'V': |
okini3939 | 0:8ba6230eefbd | 166 | i = atoi(&cmd[1]); |
okini3939 | 0:8ba6230eefbd | 167 | if (i < 0 || i > 200) break; |
okini3939 | 0:8ba6230eefbd | 168 | dac_vol = i; |
okini3939 | 0:8ba6230eefbd | 169 | DBG("volume %d\r\n", i); |
okini3939 | 0:8ba6230eefbd | 170 | r = 0; |
okini3939 | 0:8ba6230eefbd | 171 | break; |
okini3939 | 0:8ba6230eefbd | 172 | } |
okini3939 | 0:8ba6230eefbd | 173 | |
okini3939 | 0:8ba6230eefbd | 174 | return r; |
okini3939 | 0:8ba6230eefbd | 175 | } |
okini3939 | 0:8ba6230eefbd | 176 | |
okini3939 | 0:8ba6230eefbd | 177 | |
okini3939 | 0:8ba6230eefbd | 178 | /* |
okini3939 | 0:8ba6230eefbd | 179 | * This is the input callback. The purpose of this callback is to (re)fill |
okini3939 | 0:8ba6230eefbd | 180 | * the stream buffer which is to be decoded. |
okini3939 | 0:8ba6230eefbd | 181 | */ |
okini3939 | 0:8ba6230eefbd | 182 | |
okini3939 | 0:8ba6230eefbd | 183 | enum mad_flow input(void *data, |
okini3939 | 0:8ba6230eefbd | 184 | struct mad_stream *stream) |
okini3939 | 0:8ba6230eefbd | 185 | { |
okini3939 | 0:8ba6230eefbd | 186 | static unsigned char strmbuff[2100]; |
okini3939 | 0:8ba6230eefbd | 187 | int ret; |
okini3939 | 0:8ba6230eefbd | 188 | int rsz; |
okini3939 | 0:8ba6230eefbd | 189 | unsigned char *bp; |
okini3939 | 0:8ba6230eefbd | 190 | |
okini3939 | 0:8ba6230eefbd | 191 | /* the remaining bytes from incomplete frames must be copied |
okini3939 | 0:8ba6230eefbd | 192 | to the beginning of the new buffer ! |
okini3939 | 0:8ba6230eefbd | 193 | */ |
okini3939 | 0:8ba6230eefbd | 194 | bp = strmbuff; |
okini3939 | 0:8ba6230eefbd | 195 | rsz = 0; |
okini3939 | 0:8ba6230eefbd | 196 | if(stream->error == MAD_ERROR_BUFLEN||stream->buffer==NULL) { |
okini3939 | 0:8ba6230eefbd | 197 | if(stream->next_frame!=NULL) { |
okini3939 | 0:8ba6230eefbd | 198 | rsz = stream->bufend-stream->next_frame; |
okini3939 | 0:8ba6230eefbd | 199 | memmove(strmbuff,stream->next_frame,rsz); |
okini3939 | 0:8ba6230eefbd | 200 | bp = strmbuff+rsz; |
okini3939 | 0:8ba6230eefbd | 201 | } |
okini3939 | 0:8ba6230eefbd | 202 | } |
okini3939 | 0:8ba6230eefbd | 203 | |
okini3939 | 0:8ba6230eefbd | 204 | if (feof(fp)) { |
okini3939 | 0:8ba6230eefbd | 205 | if (isEmpty()) { |
okini3939 | 0:8ba6230eefbd | 206 | return MAD_FLOW_STOP; |
okini3939 | 0:8ba6230eefbd | 207 | } else { |
okini3939 | 0:8ba6230eefbd | 208 | return MAD_FLOW_CONTINUE; |
okini3939 | 0:8ba6230eefbd | 209 | } |
okini3939 | 0:8ba6230eefbd | 210 | } |
okini3939 | 0:8ba6230eefbd | 211 | |
okini3939 | 0:8ba6230eefbd | 212 | led4 = 1; |
okini3939 | 0:8ba6230eefbd | 213 | ret = fread(bp,1,sizeof(strmbuff) - rsz,fp); |
okini3939 | 0:8ba6230eefbd | 214 | |
okini3939 | 0:8ba6230eefbd | 215 | if (!ret) { |
okini3939 | 0:8ba6230eefbd | 216 | DBG("input stop\r\n"); |
okini3939 | 0:8ba6230eefbd | 217 | return MAD_FLOW_STOP; |
okini3939 | 0:8ba6230eefbd | 218 | } |
okini3939 | 0:8ba6230eefbd | 219 | |
okini3939 | 0:8ba6230eefbd | 220 | mad_stream_buffer(stream, strmbuff, ret + rsz); |
okini3939 | 0:8ba6230eefbd | 221 | |
okini3939 | 0:8ba6230eefbd | 222 | return MAD_FLOW_CONTINUE; |
okini3939 | 0:8ba6230eefbd | 223 | } |
okini3939 | 0:8ba6230eefbd | 224 | |
okini3939 | 0:8ba6230eefbd | 225 | |
okini3939 | 0:8ba6230eefbd | 226 | /* |
okini3939 | 0:8ba6230eefbd | 227 | * The following utility routine performs simple rounding, clipping, and |
okini3939 | 0:8ba6230eefbd | 228 | * scaling of MAD's high-resolution samples down to 16 bits. It does not |
okini3939 | 0:8ba6230eefbd | 229 | * perform any dithering or noise shaping, which would be recommended to |
okini3939 | 0:8ba6230eefbd | 230 | * obtain any exceptional audio quality. It is therefore not recommended to |
okini3939 | 0:8ba6230eefbd | 231 | * use this routine if high-quality output is desired. |
okini3939 | 0:8ba6230eefbd | 232 | */ |
okini3939 | 0:8ba6230eefbd | 233 | |
okini3939 | 0:8ba6230eefbd | 234 | static /*inline*/ |
okini3939 | 0:8ba6230eefbd | 235 | signed int scale(mad_fixed_t sample) |
okini3939 | 0:8ba6230eefbd | 236 | { |
okini3939 | 0:8ba6230eefbd | 237 | /* round */ |
okini3939 | 0:8ba6230eefbd | 238 | sample += (1L << (MAD_F_FRACBITS - 16)); |
okini3939 | 0:8ba6230eefbd | 239 | |
okini3939 | 0:8ba6230eefbd | 240 | /* clip */ |
okini3939 | 0:8ba6230eefbd | 241 | if (sample >= MAD_F_ONE) |
okini3939 | 0:8ba6230eefbd | 242 | sample = MAD_F_ONE - 1; |
okini3939 | 0:8ba6230eefbd | 243 | else if (sample < -MAD_F_ONE) |
okini3939 | 0:8ba6230eefbd | 244 | sample = -MAD_F_ONE; |
okini3939 | 0:8ba6230eefbd | 245 | |
okini3939 | 0:8ba6230eefbd | 246 | /* quantize */ |
okini3939 | 0:8ba6230eefbd | 247 | return sample >> (MAD_F_FRACBITS + 1 - 16); |
okini3939 | 0:8ba6230eefbd | 248 | } |
okini3939 | 0:8ba6230eefbd | 249 | |
okini3939 | 0:8ba6230eefbd | 250 | /* |
okini3939 | 0:8ba6230eefbd | 251 | * This is the output callback function. It is called after each frame of |
okini3939 | 0:8ba6230eefbd | 252 | * MPEG audio data has been completely decoded. The purpose of this callback |
okini3939 | 0:8ba6230eefbd | 253 | * is to output (or play) the decoded PCM audio. |
okini3939 | 0:8ba6230eefbd | 254 | */ |
okini3939 | 0:8ba6230eefbd | 255 | |
okini3939 | 0:8ba6230eefbd | 256 | enum mad_flow output(void *data, |
okini3939 | 0:8ba6230eefbd | 257 | struct mad_header const *header, |
okini3939 | 0:8ba6230eefbd | 258 | struct mad_pcm *pcm) |
okini3939 | 0:8ba6230eefbd | 259 | { |
okini3939 | 0:8ba6230eefbd | 260 | unsigned int nchannels, nsamples; |
okini3939 | 0:8ba6230eefbd | 261 | mad_fixed_t const *left_ch, *right_ch; |
okini3939 | 0:8ba6230eefbd | 262 | |
okini3939 | 0:8ba6230eefbd | 263 | /* pcm->samplerate contains the sampling frequency */ |
okini3939 | 0:8ba6230eefbd | 264 | nchannels = pcm->channels; |
okini3939 | 0:8ba6230eefbd | 265 | nsamples = pcm->length; |
okini3939 | 0:8ba6230eefbd | 266 | left_ch = pcm->samples[0]; |
okini3939 | 0:8ba6230eefbd | 267 | right_ch = pcm->samples[1]; |
okini3939 | 0:8ba6230eefbd | 268 | |
okini3939 | 0:8ba6230eefbd | 269 | poll(); |
okini3939 | 0:8ba6230eefbd | 270 | while (nsamples--) { |
okini3939 | 0:8ba6230eefbd | 271 | while (isFull() || available() >= (44100 * FWDBUF)) { |
okini3939 | 0:8ba6230eefbd | 272 | poll(); |
okini3939 | 0:8ba6230eefbd | 273 | if (cmd_stop) break; |
okini3939 | 0:8ba6230eefbd | 274 | } |
okini3939 | 0:8ba6230eefbd | 275 | __disable_irq(); |
okini3939 | 0:8ba6230eefbd | 276 | dacbuf[dac_w].l = scale(*left_ch); |
okini3939 | 0:8ba6230eefbd | 277 | dacbuf[dac_w].r = scale(*right_ch); |
okini3939 | 0:8ba6230eefbd | 278 | dac_w = (dac_w + 1) % DACBUF_SIZE; |
okini3939 | 0:8ba6230eefbd | 279 | if (dac_w == 0 || dac_l) dac_l ++; |
okini3939 | 0:8ba6230eefbd | 280 | __enable_irq(); |
okini3939 | 0:8ba6230eefbd | 281 | left_ch++; |
okini3939 | 0:8ba6230eefbd | 282 | right_ch++; |
okini3939 | 0:8ba6230eefbd | 283 | } |
okini3939 | 0:8ba6230eefbd | 284 | |
okini3939 | 0:8ba6230eefbd | 285 | if (cmd_stop) { |
okini3939 | 0:8ba6230eefbd | 286 | DBG("output stop o\r\n"); |
okini3939 | 0:8ba6230eefbd | 287 | cmd_stop = 0; |
okini3939 | 0:8ba6230eefbd | 288 | return MAD_FLOW_STOP; |
okini3939 | 0:8ba6230eefbd | 289 | } |
okini3939 | 0:8ba6230eefbd | 290 | return MAD_FLOW_CONTINUE; |
okini3939 | 0:8ba6230eefbd | 291 | } |
okini3939 | 0:8ba6230eefbd | 292 | |
okini3939 | 0:8ba6230eefbd | 293 | /* |
okini3939 | 0:8ba6230eefbd | 294 | * This is the error callback function. It is called whenever a decoding |
okini3939 | 0:8ba6230eefbd | 295 | * error occurs. The error is indicated by stream->error; the list of |
okini3939 | 0:8ba6230eefbd | 296 | * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h) |
okini3939 | 0:8ba6230eefbd | 297 | * header file. |
okini3939 | 0:8ba6230eefbd | 298 | */ |
okini3939 | 0:8ba6230eefbd | 299 | |
okini3939 | 0:8ba6230eefbd | 300 | enum mad_flow error_fn(void *data, |
okini3939 | 0:8ba6230eefbd | 301 | struct mad_stream *stream, |
okini3939 | 0:8ba6230eefbd | 302 | struct mad_frame *frame) |
okini3939 | 0:8ba6230eefbd | 303 | { |
okini3939 | 0:8ba6230eefbd | 304 | /* ID3 tags will cause warnings and short noise, ignore it for the moment*/ |
okini3939 | 0:8ba6230eefbd | 305 | /* |
okini3939 | 0:8ba6230eefbd | 306 | fprintf(stderr, "decoding error 0x%04x (%s)\n", |
okini3939 | 0:8ba6230eefbd | 307 | stream->error, mad_stream_errorstr(stream)); |
okini3939 | 0:8ba6230eefbd | 308 | */ |
okini3939 | 0:8ba6230eefbd | 309 | |
okini3939 | 0:8ba6230eefbd | 310 | /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ |
okini3939 | 0:8ba6230eefbd | 311 | |
okini3939 | 0:8ba6230eefbd | 312 | return MAD_FLOW_CONTINUE; |
okini3939 | 0:8ba6230eefbd | 313 | } |
okini3939 | 0:8ba6230eefbd | 314 |