/** * MP3音乐播放回调函数, * 负责将解码数据填充声音缓存区 * * @note 声音缓存区的格式为双声道,16位低字序 * * @param buf 声音缓冲区指针 * @param reqn 缓冲区帧大小 * @param pdata 用户数据,无用 */ static int mp3_audiocallback(void *buf, unsigned int reqn, void *pdata) { int avail_frame; int snd_buf_frame_size = (int) reqn; int ret; double incr; signed short *audio_buf = buf; unsigned i; uint16_t *output; UNUSED(pdata); if (g_status != ST_PLAYING) { if (handle_seek() == -1) { __end(); return -1; } xAudioClearSndBuf(buf, snd_buf_frame_size); xrKernelDelayThread(100000); return 0; } while (snd_buf_frame_size > 0) { avail_frame = g_buff_frame_size - g_buff_frame_start; if (avail_frame >= snd_buf_frame_size) { send_to_sndbuf(audio_buf, &g_buff[g_buff_frame_start * 2], snd_buf_frame_size, 2); g_buff_frame_start += snd_buf_frame_size; audio_buf += snd_buf_frame_size * 2; snd_buf_frame_size = 0; } else { send_to_sndbuf(audio_buf, &g_buff[g_buff_frame_start * 2], avail_frame, 2); snd_buf_frame_size -= avail_frame; audio_buf += avail_frame * 2; if (stream.buffer == NULL || stream.error == MAD_ERROR_BUFLEN) { size_t read_size, remaining = 0; uint8_t *read_start; int bufsize; if (stream.next_frame != NULL) { remaining = stream.bufend - stream.next_frame; memmove(g_input_buff, stream.next_frame, remaining); read_start = g_input_buff + remaining; read_size = BUFF_SIZE - remaining; } else { read_size = BUFF_SIZE; read_start = g_input_buff; remaining = 0; } if (mp3_data.use_buffer) bufsize = buffered_reader_read(mp3_data.r, read_start, read_size); else bufsize = xrIoRead(mp3_data.fd, read_start, read_size); if (bufsize <= 0) { __end(); return -1; } if (bufsize < read_size) { uint8_t *guard = read_start + read_size; memset(guard, 0, MAD_BUFFER_GUARD); read_size += MAD_BUFFER_GUARD; } mad_stream_buffer(&stream, g_input_buff, read_size + remaining); stream.error = 0; } ret = mad_frame_decode(&frame, &stream); if (ret == -1) { if (MAD_RECOVERABLE(stream.error) || stream.error == MAD_ERROR_BUFLEN) { if (stream.error == MAD_ERROR_LOSTSYNC) { long tagsize = id3_tag_query(stream.this_frame, stream.bufend - stream.this_frame); if (tagsize > 0) { mad_stream_skip(&stream, tagsize); } if (mad_header_decode(&frame.header, &stream) == -1) { if (stream.error != MAD_ERROR_BUFLEN) { if (!MAD_RECOVERABLE(stream.error)) { __end(); return -1; } } } else { stream.error = MAD_ERROR_NONE; } } g_buff_frame_size = 0; g_buff_frame_start = 0; continue; } else { __end(); return -1; } } output = &g_buff[0]; if (stream.error != MAD_ERROR_NONE) { continue; } mad_synth_frame(&synth, &frame); for (i = 0; i < synth.pcm.length; i++) { signed short sample; if (MAD_NCHANNELS(&frame.header) == 2) { /* Left channel */ sample = MadFixedToSshort(synth.pcm.samples[0][i]); *(output++) = sample; sample = MadFixedToSshort(synth.pcm.samples[1][i]); *(output++) = sample; } else { sample = MadFixedToSshort(synth.pcm.samples[0][i]); *(output++) = sample; *(output++) = sample; } } g_buff_frame_size = synth.pcm.length; g_buff_frame_start = 0; incr = frame.header.duration.seconds; incr += mad_timer_fraction(frame.header.duration, MAD_UNITS_MILLISECONDS) / 1000.0; g_play_time += incr; add_bitrate(&g_inst_br, frame.header.bitrate, incr); } } return 0; }
/* * NAME: fadein_filter() * DESCRIPTION: fade-in filter */ enum mad_flow fadein_filter(void *data, struct mad_frame *frame) { struct player *player = data; if (mad_timer_compare(player->stats.play_timer, player->fade_in) < 0) { mad_timer_t frame_start, frame_end, ratio; unsigned int nch, nsamples, s; mad_fixed_t step, scalefactor; /* * Fade-in processing may occur over the entire frame, or it may end * somewhere within the frame. Find out where processing should end. */ nsamples = MAD_NSBSAMPLES(&frame->header); /* this frame has not yet been added to play_timer */ frame_start = frame_end = player->stats.play_timer; mad_timer_add(&frame_end, frame->header.duration); if (mad_timer_compare(player->fade_in, frame_end) < 0) { mad_timer_t length; length = frame_start; mad_timer_negate(&length); mad_timer_add(&length, player->fade_in); mad_timer_set(&ratio, 0, mad_timer_count(length, frame->header.samplerate), mad_timer_count(frame->header.duration, frame->header.samplerate)); nsamples = mad_timer_fraction(ratio, nsamples); } /* determine starting scalefactor and step size */ mad_timer_set(&ratio, 0, mad_timer_count(frame_start, frame->header.samplerate), mad_timer_count(player->fade_in, frame->header.samplerate)); scalefactor = mad_timer_fraction(ratio, MAD_F_ONE); step = MAD_F_ONE / (mad_timer_count(player->fade_in, frame->header.samplerate) / 32); /* scale subband samples */ nch = MAD_NCHANNELS(&frame->header); for (s = 0; s < nsamples; ++s) { unsigned int ch, sb; for (ch = 0; ch < nch; ++ch) { for (sb = 0; sb < 32; ++sb) { frame->sbsample[ch][s][sb] = mad_f_mul(frame->sbsample[ch][s][sb], scalefactor); } } scalefactor += step; } } return MAD_FLOW_CONTINUE; }