📄 mp3_c.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 + -