⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3_c.h

📁 DC的SEGA_GG模拟器源代码
💻 H
字号:
/*
 * streamtest.c - An MP3 player using sndstream and XingMP3
 *
 * (C) 2000 Dan Potter
 */

//static char id[] = "$Id: streamtest.c,v 1.6 2001/02/05 00:53:35 bard Exp $";

#include <malloc.h>
#include <kallisti/libk.h>
#include <kallisti/abi/spu.h>
#include <kallisti/abi/maple.h>
#include <kallisti/abi/fs.h>
#include <kallisti/abi/thread.h>
#include <kallisti/abi/video.h>
#include "../kosh/abi/conio.h"

abi_spu_t	*spu;
abi_maple_t	*maple;
abi_fs_t	*fs;
abi_thread_t	*thd;
abi_video_t	*vid;
abi_conio_t	*conio;

/* To make libm happy */
int __errno;

/************************************************************************/
#include <xingmp3/mhead.h>              /* From xingmp3 */
#include <xingmp3/port.h>               /* From xingmp3 */

/* Conversion codes: generally you won't play with this stuff */
#define CONV_NORMAL	0
#define CONV_MIXMONO	1
#define CONV_DROPRIGHT	2
#define CONV_DROPLEFT	3
#define CONV_8BIT	8

/* Reduction codes: once again, generally won't play with these */
#define REDUCT_NORMAL	0
#define REDUCT_HALF	1
#define REDUCT_QUARTER	2

/* Bitstream buffer: this is for input data */
#define BS_SIZE 65536
#define BS_WATER 2048		/* One sector */
static char *bs_buffer = NULL, *bs_ptr;
static int bs_count;

/* PCM buffer: for storing data going out to the SPU */
#define PCM_WATER 65536			/* Amt to send to the SPU */
#define PCM_SIZE (PCM_WATER+16384)	/* Total buffer size */
static char *pcm_buffer = NULL, *pcm_ptr;
static int pcm_count;

/* MPEG file */
static volatile uint32	mp3_fd;
static int		frame_bytes;
static MPEG		mpeg;
static MPEG_HEAD	head;
static int		bitrate;
static DEC_INFO		decinfo;


/* Checks to make sure we have some data available in the bitstream
   buffer; if there's less than a certain "water level", shift the
   data back and bring in some more. */
int bs_fill() {
	int n;

	/* Make sure we don't underflow */
	if (bs_count < 0) bs_count = 0;

	/* Pull in some more data if we need it */
	if (bs_count < BS_WATER) {
		/* Shift everything back */
		memcpy(bs_buffer, bs_ptr, bs_count);

		/* Read in some more data */
		n = fs->read(mp3_fd, bs_buffer+bs_count, BS_SIZE - bs_count);
		if (n <= 0)
			return -1;

		/* Shift pointers back */
		bs_count += n; bs_ptr = bs_buffer;
	}

	return 0;
}

/* Empties out the last (now-used) frame of data from the PCM buffer */
int pcm_empty() {
	if (pcm_count >= PCM_WATER) {
		/* Shift everything back */
		memcpy(pcm_buffer, pcm_buffer + PCM_WATER, pcm_count - PCM_WATER);

		/* Shift pointers back */
		pcm_count -= PCM_WATER;
		pcm_ptr = pcm_buffer + pcm_count;
	}

	return 0;
}

/* This callback is called each time the sndstream driver needs
   some more data. It will tell us how much it needs in bytes. */
void* xing_callback(int size) {
	static	int frames = 0;
	IN_OUT	x;

	/* Check for file not started or file finished */
	if (mp3_fd == 0)
		return NULL;

	/* Dump the last PCM packet */
	pcm_empty();

	/* Loop decoding until we have a full buffer */
	while (pcm_count < PCM_WATER) {
		/* Pull in some more data (and check for EOF) */
		if (bs_fill() < 0 || bs_count < frame_bytes) {
			printf("\r\nDecode completed\r\n");
			goto errorout;
		}

		/* Decode a frame */
		x = audio_decode(&mpeg, bs_ptr, (short*)pcm_ptr);
		if (x.in_bytes <= 0) {
			printf("Bad sync in MPEG file\r\n");
			goto errorout;
		}

		bs_ptr += x.in_bytes; bs_count -= x.in_bytes;
		pcm_ptr += x.out_bytes; pcm_count += x.out_bytes;
		
		frames++;
		if (!(frames % 64)) {
			printf("Decoded %d frames    \r", frames);
		}
	}

	/* Got it successfully */
	return pcm_buffer;

errorout:
	fs->close(mp3_fd); mp3_fd = 0;
	return NULL;
}

/* Open an MPEG stream and prepare for decode */
int xing_init(char *fn) {
	char	*buffer;
	int	i;
	uint32	fd;

	/* Open the file */
	mp3_fd = fd = fs->open(fn, O_RDONLY);
	if (fd == 0) {
		printf("Can't open input file %s\r\n", fn);
		return -1;
	}

	/* Allocate buffers */
	if (bs_buffer == NULL)
		bs_buffer = malloc(BS_SIZE);
	bs_ptr = bs_buffer; bs_count = 0;
	if (pcm_buffer == NULL)
		pcm_buffer = malloc(PCM_SIZE);
	pcm_ptr = pcm_buffer; pcm_count = 0;

	/* Fill bitstream buffer */
	if (bs_fill() < 0) {
		printf("Can't read file header\r\n");
		goto errorout;
	}

	/* Are we looking at a RIFF file? (stupid Windows encoders) */
	if (bs_ptr[0] == 'R' && bs_ptr[1] == 'I' && bs_ptr[2] == 'F' && bs_ptr[3] == 'F') {
		/* Found a RIFF header, scan through it until we find the data section */
		printf("Skipping stupid RIFF header\r\n");
		while (bs_ptr[0] != 'd' || bs_ptr[1] != 'a' || bs_ptr[2] != 't' || bs_ptr[3] != 'a') {
			bs_ptr++;
			if (bs_ptr >= (bs_buffer + BS_SIZE)) {
				printf("Indeterminately long RIFF header\r\n");
				goto errorout;
			}
		}

		/* Skip 'data' and length */
		bs_ptr += 8;
		bs_count -= (bs_ptr - bs_buffer);
	}

	/* Initialize MPEG engines */
	mpeg_init(&mpeg);
	mpeg_eq_init(&mpeg);

	/* Parse MPEG header */
	frame_bytes = head_info2(bs_ptr, bs_count, &head, &bitrate);
	if (frame_bytes == 0) {
		printf("Bad or unsupported MPEG file\r\n");
		goto errorout;
	}

	/* Print out some info about it */
	{
		char *layers[] = { "invalid", "3", "2", "1" };
		char *modes[] = { "stereo", "joint-stereo", "dual", "mono" };
		int srs[] = { 22050, 24000, 16000, 1, 44100, 48000, 32000, 1 };

		printf("Opened stream %s for decoding:\r\n", fn);
		printf("  %dKbps Layer %s %s at %dHz\r\n",
			bitrate/1000, layers[head.option], modes[head.mode],
			srs[4*head.id + head.sr_index]);
	}

	/* Initialize audio decoder */
	if (!audio_decode_init(&mpeg, &head, frame_bytes,
			REDUCT_NORMAL, 0, CONV_NORMAL, 44100)) {
		printf("Failed to initialize decoder\r\n");
		goto errorout;
	}
	audio_decode_info(&mpeg, &decinfo);
	printf("Output Sampling rate = %ld\r\n", decinfo.samprate);
	printf("Output Channels      = %d\r\n", decinfo.channels);
	printf("Output Bits          = %d\r\n", decinfo.bits);
	printf("Output Type          = %d\r\n", decinfo.type);
	if (decinfo.samprate != 44100) {
		printf("Currently cannot process %d sampling rate\r\n", decinfo.samprate);
		goto errorout;
	}

	printf("XingMP3 initialized successfully\r\n");
	return 0;

errorout:
	printf("Exiting on error\r\n");
	free(bs_buffer);
	free(pcm_buffer);
	fs->close(fd);
	return -1;
}

void xing_shutdown() {
	if (bs_buffer) {
		free(bs_buffer);
		bs_buffer = NULL;
	}
	if (pcm_buffer) { 
		free(pcm_buffer);
		pcm_buffer = NULL;
	}
}

/************************************************************************/
#include "sndstream.h"

void wait_start() {
	cont_cond_t cond;

	while (mp3_fd > 0) {
		if (!conio) {
			if (maple->cont_get_cond(maple->first_controller(), &cond) < 0) {
				printf("Can't read controller status\r\n");
				break;
			}
			if (!(cond.buttons & CONT_START)) break;
		} else {
			if (conio->check_getch() != -1)
				break;
		}
		stream_poll();
		thd->sleep(10);
	}
}

void mp3_play() {
        if (kos_stream_init(xing_callback) < 0) return;
	stream_start();

	thd->sleep(100);
	wait_start();

	spu->disable();
	
	stream_shutdown();
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -