#ifdef __GP2X__
void mp3_update_local(int *buffer, int length, int stereo);
-void mp3_start_local(void);
+void mp3_start_play_local(FILE *f, int pos);
#endif
#include <stdio.h>
#include <string.h>
-#include "../../pico/pico_int.h"
-#include "../../pico/sound/mix.h"
+#include <pico/pico_int.h>
+#include <pico/sound/mix.h>
#include "helix/pub/mp3dec.h"
+#include "mp3.h"
#include "lprintf.h"
static HMP3Decoder mp3dec = 0;
+static FILE *mp3_current_file = NULL;
+static int mp3_file_len = 0, mp3_file_pos = 0;
static int mp3_buffer_offs = 0;
+static unsigned char mp3_input_buffer[2*1024];
+#ifdef __GP2X__
+#define mp3_update mp3_update_local
+#define mp3_start_play mp3_start_play_local
+#endif
static int find_sync_word(unsigned char *buf, int nBytes)
{
return -1;
}
-
static int try_get_header(unsigned char *buff, MP3FrameInfo *fi)
{
int ret, offs1, offs = 0;
return fi.bitrate / 1000;
}
-
-#ifdef __GP2X__
-
-#include "../gp2x/code940/940shared.h"
-
-extern _940_ctl_t *shared_ctl;
-extern unsigned char *mp3_mem;
-
-static int mp3_decode(void)
-{
- // tried copying this to cached mem, no improvement noticed
- int mp3_offs = shared_ctl->mp3_offs;
- unsigned char *readPtr = mp3_mem + mp3_offs;
- int bytesLeft = shared_ctl->mp3_len - mp3_offs;
- int offset; // frame offset from readPtr
- int retries = 0, err;
-
- if (bytesLeft <= 0) return 1; // EOF, nothing to do
-
-retry:
- offset = find_sync_word(readPtr, bytesLeft);
- if (offset < 0) {
- shared_ctl->mp3_offs = shared_ctl->mp3_len;
- return 1; // EOF
- }
- readPtr += offset;
- bytesLeft -= offset;
-
- err = MP3Decode(mp3dec, &readPtr, &bytesLeft, cdda_out_buffer, 0);
- if (err) {
- if (err == ERR_MP3_INDATA_UNDERFLOW) {
- shared_ctl->mp3_offs = shared_ctl->mp3_len; // EOF
- return 1;
- } else if (err <= -6 && err >= -12) {
- // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*
- // just try to skip the offending frame..
- readPtr++;
- bytesLeft--;
- if (retries++ < 2) goto retry;
- else lprintf("mp3 decode failed with %i after %i retries\n", err, retries);
- }
- shared_ctl->mp3_errors++;
- shared_ctl->mp3_lasterr = err;
- }
- shared_ctl->mp3_offs = readPtr - mp3_mem;
- return 0;
-}
-
-void mp3_start_local(void)
-{
- // must re-init decoder for new track
- if (mp3dec) MP3FreeDecoder(mp3dec);
- mp3dec = MP3InitDecoder();
-
- mp3_buffer_offs = 0;
- mp3_decode();
-}
-
-#define mp3_update mp3_update_local
-
-#else // !__GP2X__
-
-static FILE *mp3_current_file = NULL;
-static int mp3_file_len = 0, mp3_file_pos = 0;
-static unsigned char mp3_input_buffer[2*1024];
-
static int mp3_decode(void)
{
unsigned char *readPtr;
int bytesLeft;
int offset; // mp3 frame offset from readPtr
- int err;
+ int had_err;
+ int err = 0;
do
{
- if (mp3_file_pos >= mp3_file_len) return 1; // EOF, nothing to do
+ if (mp3_file_pos >= mp3_file_len)
+ return 1; /* EOF, nothing to do */
fseek(mp3_current_file, mp3_file_pos, SEEK_SET);
bytesLeft = fread(mp3_input_buffer, 1, sizeof(mp3_input_buffer), mp3_current_file);
offset = find_sync_word(mp3_input_buffer, bytesLeft);
if (offset < 0) {
- //lprintf("find_sync_word (%i/%i) err %i\n", mp3_file_pos, mp3_file_len, offset);
+ lprintf("find_sync_word (%i/%i) err %i\n", mp3_file_pos, mp3_file_len, offset);
mp3_file_pos = mp3_file_len;
return 1; // EOF
}
readPtr = mp3_input_buffer + offset;
bytesLeft -= offset;
+ had_err = err;
err = MP3Decode(mp3dec, &readPtr, &bytesLeft, cdda_out_buffer, 0);
if (err) {
- //lprintf("MP3Decode err (%i/%i) %i\n", mp3_file_pos, mp3_file_len, err);
- if (err == ERR_MP3_INDATA_UNDERFLOW) {
+ if (err == ERR_MP3_MAINDATA_UNDERFLOW && !had_err) {
+ // just need another frame
+ mp3_file_pos += readPtr - mp3_input_buffer;
+ continue;
+ }
+ if (err == ERR_MP3_INDATA_UNDERFLOW && !had_err) {
if (offset == 0)
// something's really wrong here, frame had to fit
mp3_file_pos = mp3_file_len;
else
mp3_file_pos += offset;
continue;
- } else if (err <= -6 && err >= -12) {
+ }
+ if (-12 <= err && err <= -6) {
// ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*
// just try to skip the offending frame..
mp3_file_pos += offset + 1;
continue;
}
+ lprintf("MP3Decode err (%i/%i) %i\n", mp3_file_pos, mp3_file_len, err);
mp3_file_pos = mp3_file_len;
return 1;
}
mp3_current_file = NULL;
mp3_buffer_offs = 0;
- // must re-init decoder for new track
- if (mp3dec) MP3FreeDecoder(mp3dec);
- mp3dec = MP3InitDecoder();
-
- if (!(PicoOpt&POPT_EN_MCD_CDDA) || f == NULL) // cdda disabled or no file?
+ if (!(PicoOpt & POPT_EN_MCD_CDDA) || f == NULL) // cdda disabled or no file?
return;
- //lprintf("mp3_start_play %p %i\n", f, pos);
+ // must re-init decoder for new track
+ if (mp3dec)
+ MP3FreeDecoder(mp3dec);
+ mp3dec = MP3InitDecoder();
mp3_current_file = f;
fseek(f, 0, SEEK_END);
// seek..
if (pos) {
- mp3_file_pos = (mp3_file_len << 6) >> 10;
- mp3_file_pos *= pos;
- mp3_file_pos >>= 6;
+ unsigned long long pos64 = mp3_file_len;
+ pos64 *= pos;
+ mp3_file_pos = pos64 >> 10;
}
mp3_decode();
}
-int mp3_get_offset(void)
-{
- unsigned int offs1024 = 0;
- int cdda_on;
-
- cdda_on = (PicoAHW & PAHW_MCD) && (PicoOpt&POPT_EN_MCD_CDDA) && !(Pico_mcd->s68k_regs[0x36] & 1) &&
- (Pico_mcd->scd.Status_CDC & 1) && mp3_current_file != NULL;
-
- if (cdda_on) {
- offs1024 = mp3_file_pos << 7;
- offs1024 /= mp3_file_len >> 3;
- }
- //lprintf("mp3_get_offset offs1024=%u (%i/%i)\n", offs1024, mp3_file_pos, mp3_file_len);
-
- return offs1024;
-}
-
-#endif // ifndef __GP2X__
-
void mp3_update(int *buffer, int length, int stereo)
{
int length_mp3, shr = 0;
void (*mix_samples)(int *dest_buf, short *mp3_buf, int count) = mix_16h_to_32;
-#ifndef __GP2X__
- if (mp3_current_file == NULL || mp3_file_pos >= mp3_file_len) return; // no file / EOF
-#endif
+ if (mp3_current_file == NULL || mp3_file_pos >= mp3_file_len)
+ return; /* no file / EOF */
length_mp3 = length;
if (PsndRate == 22050) { mix_samples = mix_16h_to_32_s1; length_mp3 <<= 1; shr = 1; }
}
}
-
}\r
\r
\r
+/***********************************************************/\r
+\r
static int mp3_samples_ready = 0, mp3_buffer_offs = 0;\r
static int mp3_play_bufsel = 0, mp3_job_started = 0;\r
\r
void mp3_update(int *buffer, int length, int stereo)\r
{\r
int length_mp3;\r
- int cdda_on;\r
-\r
- // playback was started, track not ended\r
- cdda_on = loaded_mp3 && shared_ctl->mp3_offs < shared_ctl->mp3_len;\r
\r
- if (!cdda_on) return;\r
-\r
- if (!(PicoOpt&0x200)) {\r
+ if (!(PicoOpt & POPT_EXT_FM)) {\r
mp3_update_local(buffer, length, stereo);\r
return;\r
}\r
\r
+ // check if playback was started, track not ended\r
+ if (loaded_mp3 == NULL || shared_ctl->mp3_offs >= shared_ctl->mp3_len)\r
+ return;\r
+\r
length_mp3 = length;\r
if (PsndRate == 22050) length_mp3 <<= 1; // mp3s are locked to 44100Hz stereo\r
else if (PsndRate == 11025) length_mp3 <<= 2; // so make length 44100ish\r
}\r
\r
\r
-/***********************************************************/\r
-\r
void mp3_start_play(FILE *f, int pos) // pos is 0-1023\r
{\r
int byte_offs = 0;\r
\r
- if (!(PicoOpt&0x800)) { // cdda disabled?\r
+ if (!(PicoOpt & POPT_EN_MCD_CDDA) || f == NULL)\r
+ return;\r
+\r
+ if (!(PicoOpt & POPT_EXT_FM)) {\r
+ mp3_start_play_local(f, pos);\r
return;\r
}\r
\r
mp3_job_started = 0;\r
shared_ctl->mp3_buffsel = 1; // will change to 0 on first decode\r
\r
- if (PicoOpt & POPT_EXT_FM)\r
- {\r
- add_job_940(JOB940_MP3RESET);\r
- if (CHECK_BUSY(JOB940_MP3RESET)) wait_busy_940(JOB940_MP3RESET);\r
- }\r
- else\r
- mp3_start_local();\r
-}\r
-\r
-\r
-int mp3_get_offset(void)\r
-{\r
- unsigned int offs1024 = 0;\r
- int cdda_on;\r
-\r
- cdda_on = (PicoAHW & PAHW_MCD) && (PicoOpt&0x800) && !(Pico_mcd->s68k_regs[0x36] & 1) &&\r
- (Pico_mcd->scd.Status_CDC & 1) && loaded_mp3;\r
-\r
- if (cdda_on) {\r
- offs1024 = shared_ctl->mp3_offs << 7;\r
- offs1024 /= shared_ctl->mp3_len >> 3;\r
- }\r
- printf("offs1024=%u (%i/%i)\n", offs1024, shared_ctl->mp3_offs, shared_ctl->mp3_len);\r
-\r
- return offs1024;\r
+ add_job_940(JOB940_MP3RESET);\r
+ if (CHECK_BUSY(JOB940_MP3RESET)) wait_busy_940(JOB940_MP3RESET);\r
}\r
\r
-\r
\r
if (bytesLeft <= 0) return; // EOF, nothing to do\r
\r
-retry:\r
- offset = find_sync_word(readPtr, bytesLeft);\r
- if (offset < 0) {\r
- set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, shared_ctl->mp3_len);\r
- return; // EOF\r
- }\r
- readPtr += offset;\r
- bytesLeft -= offset;\r
-\r
- err = MP3Decode(shared_data->mp3dec, &readPtr, &bytesLeft,\r
- shared_data->mp3_buffer[shared_ctl->mp3_buffsel], 0);\r
- if (err) {\r
- if (err == ERR_MP3_INDATA_UNDERFLOW) {\r
- set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, shared_ctl->mp3_len);\r
- return;\r
- } else if (err <= -6 && err >= -12) {\r
- // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*\r
- // just try to skip the offending frame..\r
- readPtr++;\r
- bytesLeft--;\r
- if (retries++ < 2) goto retry;\r
+ for (retries = 0; retries < 2; retries++)\r
+ {\r
+ offset = find_sync_word(readPtr, bytesLeft);\r
+ if (offset < 0)\r
+ goto set_eof;\r
+\r
+ readPtr += offset;\r
+ bytesLeft -= offset;\r
+\r
+ err = MP3Decode(shared_data->mp3dec, &readPtr, &bytesLeft,\r
+ shared_data->mp3_buffer[shared_ctl->mp3_buffsel], 0);\r
+ if (err) {\r
+ if (err == ERR_MP3_MAINDATA_UNDERFLOW)\r
+ // just need another frame\r
+ continue;\r
+\r
+ if (err == ERR_MP3_INDATA_UNDERFLOW)\r
+ goto set_eof;\r
+\r
+ if (err <= -6 && err >= -12) {\r
+ // ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*\r
+ // just try to skip the offending frame..\r
+ readPtr++;\r
+ bytesLeft--;\r
+ continue;\r
+ }\r
+ shared_ctl->mp3_errors++;\r
+ shared_ctl->mp3_lasterr = err;\r
}\r
- shared_ctl->mp3_errors++;\r
- shared_ctl->mp3_lasterr = err;\r
+ break;\r
}\r
+\r
set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, readPtr - mp3_data);\r
+ return;\r
+\r
+set_eof:\r
+ set_if_not_changed(&shared_ctl->mp3_offs, mp3_offs, shared_ctl->mp3_len);\r
}\r
\r
static void ym_flush_writes(void)\r
# settings\r
#up = 1\r
\r
-DEFINC = -I../.. -I. -D__GP2X__ -DARM # -DBENCHMARK\r
-COPT_COMMON = -static -s -O2 -ftracer -fstrength-reduce -Wall -fomit-frame-pointer -fstrict-aliasing -ffast-math\r
-COPT = $(COPT_COMMON) -mtune=arm940t\r
+DEFINC = -I../.. -I. -D__GP2X__ -DARM\r
+# -ftracer\r
+COPT_COMMON = -static -s -O2 -Wall -fomit-frame-pointer -fstrict-aliasing -ffast-math\r
+CFLAGS = $(COPT_COMMON) $(DEFINC) -mcpu=arm940t -mtune=arm940t\r
GCC = $(CROSS)gcc\r
STRIP = $(CROSS)strip\r
AS = $(CROSS)as\r
\r
.c.o:\r
@echo ">>>" $<\r
- $(GCC) $(COPT) $(DEFINC) -c $< -o $@\r
+ $(GCC) $(CFLAGS) -c $< -o $@\r
.s.o:\r
@echo ">>>" $<\r
- $(GCC) $(COPT) $(DEFINC) -c $< -o $@\r
+ $(GCC) $(CFLAGS) -c $< -o $@\r
\r
\r
# stuff for 940 core\r
\r
# init, emu_control, emu\r
-OBJS940 += 940init.o 940.o 940ym2612.o memcpy.o mix.o misc.o\r
+OBJS940 += 940init.o 940.o 940ym2612.o memcpy.o misc_arm.o\r
# the asm code seems to be faster when run on 920, but not on 940 for some reason\r
# OBJS940 += ../../Pico/sound/ym2612_asm.o\r
\r
OBJS940 += uClibc/s_scalbn.o uClibc/s_copysign.o uClibc/k_sin.o uClibc/k_cos.o uClibc/s_sin.o\r
OBJS940 += uClibc/e_rem_pio2.o uClibc/k_rem_pio2.o uClibc/e_log.o uClibc/wrappers.o\r
\r
-$(BIN) : code940.gpe\r
+$(BIN) : code940.elf\r
@echo ">>>" $@\r
$(OBJCOPY) -O binary $< $@\r
\r
-code940.gpe : $(OBJS940) ../../common/helix/helix_mp3.a\r
+code940.elf : $(OBJS940) ../../common/helix/$(CROSS)helix-mp3.a\r
@echo ">>>" $@\r
$(LD) -static -e code940 -Ttext 0x0 $^ -L$(lgcc_path) -lgcc -o $@ -Map code940.map\r
\r
-940ym2612.o : ../../../Pico/sound/ym2612.c\r
+940ym2612.o : ../../../pico/sound/ym2612.c\r
@echo ">>>" $@\r
- $(GCC) $(COPT) -Os $(DEFINC) -DEXTERNAL_YM2612 -c $< -o $@\r
+ $(GCC) $(CFLAGS) -Os -DEXTERNAL_YM2612 -c $< -o $@\r
\r
-mix.o : ../../../Pico/sound/mix.s\r
+mix.o : ../../../pico/sound/mix.s\r
@echo ">>>" $@\r
- $(GCC) $(COPT) $(DEFINC) -DEXTERNAL_YM2612 -c $< -o $@\r
-misc.o : ../../../Pico/Misc.s\r
+ $(GCC) $(CFLAGS) -DEXTERNAL_YM2612 -c $< -o $@\r
+misc_arm.o : ../../../pico/misc_arm.s\r
@echo ">>>" $@\r
- $(GCC) $(COPT) $(DEFINC) -DEXTERNAL_YM2612 -c $< -o $@\r
+ $(GCC) $(CFLAGS) -DEXTERNAL_YM2612 -c $< -o $@\r
\r
../../common/helix/helix_mp3.a:\r
@make -C ../../common/helix/\r
\r
# cleanup\r
clean: tidy\r
- @$(RM) code940.bin\r
+ $(RM) $(BIN)\r
tidy:\r
- @$(RM) code940.gpe $(OBJS940) code940.map\r
+ $(RM) code940.elf $(OBJS940) code940.map\r
\r
\r
OBJSMP3T = mp3test.o ../gp2x.o ../asmutils.o ../usbjoy.o\r
\r
# uClibc/e_pow.o : uClibc/e_pow.c\r
# @echo $<\r
-# @$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@\r
+# @$(GCC) $(CFLAGS) -fno-profile-generate -c $< -o $@\r
\r
# uClibc/e_sqrt.o : uClibc/e_sqrt.c\r
# @echo $<\r
-# @$(GCC) $(COPT) $(DEFINC) -fno-profile-generate -c $< -o $@\r
+# @$(GCC) $(CFLAGS) -fno-profile-generate -c $< -o $@\r
{\r
plat_status_msg_clear();\r
pemu_update_display("", msg);\r
+ emu_status_msg("");\r
\r
/* assumption: msg_busy_next gets called only when\r
* something slow is about to happen */\r
void pemu_sound_start(void)\r
{\r
static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0;\r
- int target_fps = Pico.m.pal ? 50 : 60;\r
\r
PsndOut = NULL;\r
\r
// prepare sound stuff\r
- if (currentConfig.EmuOpt & 4)\r
+ if (currentConfig.EmuOpt & EOPT_EN_SOUND)\r
{\r
+ int is_stereo = (PicoOpt & POPT_EN_STEREO) ? 1 : 0;\r
+ int target_fps = Pico.m.pal ? 50 : 60;\r
int snd_excess_add;\r
- if (PsndRate != PsndRate_old || (PicoOpt&0x20b) != (PicoOpt_old&0x20b) || Pico.m.pal != pal_old ||\r
- ((PicoOpt&0x200) && crashed_940)) {\r
+ gp2x_soc_t soc;\r
+\r
+ #define SOUND_RERATE_FLAGS (POPT_EN_FM|POPT_EN_PSG|POPT_EN_STEREO|POPT_EXT_FM|POPT_EN_MCD_CDDA)\r
+ if (PsndRate != PsndRate_old || Pico.m.pal != pal_old || ((PicoOpt & POPT_EXT_FM) && crashed_940) ||\r
+ ((PicoOpt ^ PicoOpt_old) & SOUND_RERATE_FLAGS)) {\r
PsndRerate(Pico.m.frame_count ? 1 : 0);\r
}\r
- snd_excess_add = ((PsndRate - PsndLen*target_fps)<<16) / target_fps;\r
+ snd_excess_add = ((PsndRate - PsndLen * target_fps)<<16) / target_fps;\r
printf("starting audio: %i len: %i (ex: %04x) stereo: %i, pal: %i\n",\r
- PsndRate, PsndLen, snd_excess_add, (PicoOpt&8)>>3, Pico.m.pal);\r
- sndout_oss_start(PsndRate, 16, (PicoOpt&8)>>3);\r
+ PsndRate, PsndLen, snd_excess_add, is_stereo, Pico.m.pal);\r
+ sndout_oss_start(PsndRate, 16, is_stereo);\r
sndout_oss_setvol(currentConfig.volume, currentConfig.volume);\r
PicoWriteSound = updateSound;\r
plat_update_volume(0, 0);\r
PsndRate_old = PsndRate;\r
PicoOpt_old = PicoOpt;\r
pal_old = Pico.m.pal;\r
+\r
+ /* Wiz's sound hardware needs more prebuffer */\r
+ soc = soc_detect();\r
+ if (soc == SOCID_POLLUX)\r
+ updateSound(PsndLen);\r
}\r
}\r
\r