int32_t buffered_reader_read(buffered_reader_t * reader, void *buffer, uint32_t size)
{
	if (!reader->cache_enabled) {
		return sceIoRead(reader->handle, buffer, size);
	}

	if (reader->current_position == reader->length)
		return 0;
	if (size <= reader->position_2 - reader->current_position) {
		if (reader->current_position < reader->position_1) {
			if (size <= reader->position_1 - reader->current_position) {
				memcpy(buffer, reader->first_buffer + (reader->current_position - reader->position_0), size);
			} else {
				memcpy(buffer, reader->first_buffer + (reader->current_position - reader->position_0), reader->position_1 - reader->current_position);
				memcpy(buffer + (reader->position_1 - reader->current_position), reader->second_buffer, size - (reader->position_1 - reader->current_position));
			}
		} else {
			memcpy(buffer, reader->second_buffer + (reader->current_position - reader->position_1), size);
		}
		reader->current_position += size;
		if (reader->current_position == reader->position_2)
			buffered_reader_seek(reader, reader->position_2);
		return size;
	} else {
		uint32_t data_size;

		data_size = reader->position_2 - reader->current_position;
		buffered_reader_read(reader, buffer, data_size);
		data_size += buffered_reader_read(reader, buffer + data_size, size - data_size);
		return data_size;
	}
}
Exemple #2
0
/**
 * MP3音乐播放回调函数,ME版本
 * 负责将解码数据填充声音缓存区
 *
 * @note 声音缓存区的格式为双声道,16位低字序
 *
 * @param buf 声音缓冲区指针
 * @param reqn 缓冲区帧大小
 * @param pdata 用户数据,无用
 */
static int memp3_audiocallback(void *buf, unsigned int reqn, void *pdata)
{
	int avail_frame;
	int snd_buf_frame_size = (int) reqn;
	signed short *audio_buf = buf;
	double incr;
	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 {
			int frame_size, ret, brate = 0;

			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;

			do {
				if (mp3_data.use_buffer) {
					if ((frame_size =
						 search_valid_frame_me_buffered(&mp3_data,
														&brate)) < 0) {
						__end();
						return -1;
					}
				} else {
					if ((frame_size =
						 search_valid_frame_me(&mp3_data, &brate)) < 0) {
						__end();
						return -1;
					}
				}

				if (mp3_data.use_buffer)
					ret =
						buffered_reader_read(mp3_data.r, memp3_input_buf,
											 frame_size);
				else
					ret = xrIoRead(mp3_data.fd, memp3_input_buf, frame_size);

				if (ret < 0) {
					__end();
					return -1;
				}

				ret = memp3_decode(memp3_input_buf, ret, memp3_decoded_buf);
			} while (ret < 0);

			output = &g_buff[0];

			memcpy(output, memp3_decoded_buf, mp3info.spf * 4);
			g_buff_frame_size = mp3info.spf;
			g_buff_frame_start = 0;
			incr = (double) mp3info.spf / mp3info.sample_freq;
			g_play_time += incr;

			add_bitrate(&g_inst_br, brate * 1000, incr);
		}
	}

	return 0;
}
Exemple #3
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;
}
Exemple #4
0
/**
 * 搜索下一个有效MP3 frame
 *
 * @return
 * - <0 失败
 * - 0 成功
 */
static int seek_valid_frame(void)
{
	int cnt = 0;
	int ret;

	mad_stream_finish(&stream);
	mad_stream_init(&stream);

	do {
		cnt++;
		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) {
				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;
		}

		if ((ret = mad_header_decode(&frame.header, &stream)) == -1) {
			/*
			 * MAD_ERROR_BUFLEN should be ignored
			 *
			 * We haven't reached the EOF as long as xrIoRead returned positive.
			 */
			if (!MAD_RECOVERABLE(stream.error) && stream.error != MAD_ERROR_BUFLEN) {
				return -1;
			}
		} else {
			ret = 0;
			stream.error = 0;
		}
	} while (!(ret == 0 && stream.sync == 1));
	dbg_printf(d, "%s: tried %d times", __func__, cnt);

	return 0;
}