Example #1
0
/**
 * 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;
}
Example #2
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;
}