has anyone got FLAC code?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Viper8896
Posts: 110
Joined: Thu Jan 26, 2006 6:20 pm

has anyone got FLAC code?

Post by Viper8896 »

has anyone here ported over the FLAC library to the psp (and like to share) bcos i noticed that on qj net someone released an app called flacplay but he didn't release any source code with it.
weltall
Posts: 310
Joined: Fri Feb 20, 2004 1:56 am
Contact:

Re: has anyone got FLAC code?

Post by weltall »

Viper8896 wrote:has anyone here ported over the FLAC library to the psp (and like to share) bcos i noticed that on qj net someone released an app called flacplay but he didn't release any source code with it.
flac is bsd so they aren't obliged to release it.
you may have a look at http://sourceforge.net/project/showfile ... e_id=12677
Viper8896
Posts: 110
Joined: Thu Jan 26, 2006 6:20 pm

Post by Viper8896 »

no i don't think you read me correctly. i'm aware of flacs license and availability I was looking for already ported code.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

You're in luck, FLAC is easy to get on the PSP. First start by making libFLAC.

Code: Select all

1 - Download latest flac source archive from SourceForge.

http://sourceforge.net/project/showfiles.php?group_id=13478&package_id=12677

2 - Unpack archive.

3 - Edit config.sub: look for

	ps2)
		basic_machine=i386-ibm
		;;


and paste this right after it

	psp)
		basic_machine=mipsallegrexel-psp
		os=-elf
		;;

4 - Run:

CFLAGS="-ffast-math -fsigned-char -G0" LDFLAGS="-L$(psp-config --pspsdk-path)/lib -lc -lpspuser" ./configure --enable-maintainer-mode --host=psp --prefix=$(psp-config --psp-prefix) --with-ogg=$(psp-config --psp-prefix)
cd src/libFLAC
make
make install
cd ../../include/FLAC
make
make install
You now have libFLAC and the necessary includes in your PSPSDK lib/include directories. Now you just need to use it. I modified my simple ogg player so that it now plays oggs and flacs. Note that flac is not compatible with tremor. You wind up with multiply defined functions. You have to use ogg with flac. Oh well. Here's the code and makefile for my simple ogg player, which now also plays flacs.

makefile

Code: Select all

TARGET = OggPlayer
OBJS = main.o reqfile.o

INCDIR =
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

BUILD_PRX = 1
PSP_FW_VERSION = 371

LIBDIR =
#LIBS = -lvorbisidec -lvorbis -logg -lpspaudiolib -lpspaudio -lpsppower
LIBS = -lFLAC -lvorbisfile -lvorbis -logg -lpspaudiolib -lpspaudio -lpsppower -lm
LDFLAGS =

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Simple Ogg Player
PSP_EBOOT_ICON="icon0.png"
#PSP_EBOOT_PIC1="pic1.png"
#PSP_EBOOT_SND0="snd0.at3"

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
main.c

Code: Select all

#include <pspkernel.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <pspaudio.h>
#include <pspaudiolib.h>
#include <psppower.h>
#include <pspdisplay.h>
#include <string.h>
#include <stdio.h>

//#include <tremor/ivorbiscodec.h>
//#include <tremor/ivorbisfile.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>

#include <FLAC/stream_decoder.h>

#define printf pspDebugScreenPrintf

#define VERS	 1
#define REVS	 0

extern char *RequestFile&#40;char *&#41;;

PSP_MODULE_INFO&#40;"OggPlayer", 0, VERS, REVS&#41;;
PSP_MAIN_THREAD_ATTR&#40;PSP_THREAD_ATTR_USER&#41;;
PSP_HEAP_SIZE_MAX&#40;&#41;;

#define OUTPUT_BUFFER 32768  // must be less than PSP_AUDIO_SAMPLE_MAX*4

/////////////////////////////////////////////////////////////////////////////////////////
//Globals
/////////////////////////////////////////////////////////////////////////////////////////

int runningFlag;
int bufferEmpty;
int bufferFull;

int audioVol = PSP_AUDIO_VOLUME_MAX;

char pcmout1&#91;OUTPUT_BUFFER&#93;;
char pcmout2&#91;OUTPUT_BUFFER&#93;;
long pcmlen1, pcmlen2;
int bufferFlip = 0;

// Ogg variables

OggVorbis_File OGG_VorbisFile;
int OGG_eos = 0;
int OGG_audio_channel = 0;
int bitStream;
FILE *the_file = 0;

// FLAC variables

FLAC__uint64 total_samples = 0;
unsigned int sample_rate = 0;
unsigned int channels = 0;
unsigned int bps = 0;

/////////////////////////////////////////////////////////////////////////////////////////
//Callbacks
/////////////////////////////////////////////////////////////////////////////////////////

/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41; &#123;
	sceKernelExitGame&#40;&#41;;
	return 0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41; &#123;
	int cbid;

	cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
	sceKernelRegisterExitCallback&#40;cbid&#41;;
	sceKernelSleepThreadCB&#40;&#41;;
	return 0;
&#125;

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks&#40;void&#41; &#123;
	int thid = 0;

	thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0&#41;;
	if&#40;thid >= 0&#41; &#123;
		sceKernelStartThread&#40;thid, 0, 0&#41;;
	&#125;

	return thid;
&#125;


/////////////////////////////////////////////////////////////////////////////////////////
//FLAC callbacks
/////////////////////////////////////////////////////////////////////////////////////////

FLAC__StreamDecoderWriteStatus write_callback&#40;const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer&#91;&#93;, void *client_data&#41;
&#123;
//	FILE *f = &#40;FILE*&#41;client_data;
//	const FLAC__uint32 total_size = &#40;FLAC__uint32&#41;&#40;total_samples * channels * &#40;bps/8&#41;&#41;;
	int i;
	FLAC__int16 *fillbuf;
	SceCtrlData pad;

	&#40;void&#41;decoder, &#40;void&#41;client_data;

	if&#40;channels != 2 || bps != 16&#41;
	&#123;
		printf&#40;" ERROR&#58; this player only supports 16bit stereo streams\n"&#41;;
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
	&#125;

	/* copy decoded PCM samples to buffer */
	sceKernelWaitSema&#40;bufferEmpty, 1, 0&#41;;

	fillbuf = bufferFlip ? &#40;FLAC__int16 *&#41;pcmout2 &#58; &#40;FLAC__int16 *&#41;pcmout1;
	for &#40;i=0; i<frame->header.blocksize; i++&#41;
	&#123;
		fillbuf&#91;i<<1&#93; = &#40;FLAC__int16&#41;buffer&#91;0&#93;&#91;i&#93;;
		fillbuf&#91;&#40;i<<1&#41;+1&#93; = &#40;FLAC__int16&#41;buffer&#91;1&#93;&#91;i&#93;;
	&#125;
	if &#40;bufferFlip&#41;
		pcmlen2 = frame->header.blocksize<<2;
	else
		pcmlen1 = frame->header.blocksize<<2;
	sceKernelSignalSema&#40;bufferFull, 1&#41;;

	sceCtrlReadBufferPositive&#40;&pad, 1&#41;;
	if&#40;pad.Buttons & PSP_CTRL_CROSS&#41;
		return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;

	if &#40;pad.Buttons & PSP_CTRL_LTRIGGER&#41;
		if &#40;audioVol > 0&#41;
			audioVol -= 0x0800; // 16 steps on the audio

	if &#40;pad.Buttons & PSP_CTRL_RTRIGGER&#41;
		if &#40;audioVol < 0x8000&#41;
			audioVol += 0x0800; // 16 steps on the audio

	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
&#125;

void metadata_callback&#40;const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data&#41;
&#123;
	int secs = 0;
	int h = 0;
	int m = 0;
	int s = 0;
	char dest&#91;9&#93;;

	&#40;void&#41;decoder, &#40;void&#41;client_data;

	/* print some stats */
	if&#40;metadata->type == FLAC__METADATA_TYPE_STREAMINFO&#41; &#123;
		/* save for later */
		total_samples = metadata->data.stream_info.total_samples;
		sample_rate = metadata->data.stream_info.sample_rate;
		channels = metadata->data.stream_info.channels;
		bps = metadata->data.stream_info.bits_per_sample;

		printf&#40;" sample rate    &#58; %u Hz\n", sample_rate&#41;;
		printf&#40;" channels       &#58; %u\n", channels&#41;;
		printf&#40;" bits per sample&#58; %u\n", bps&#41;;

		secs = total_samples/sample_rate;
		h = secs / 3600;
		m = &#40;secs - h * 3600&#41; / 60;
		s = secs - h * 3600 - m * 60;
		snprintf&#40;dest, sizeof&#40;dest&#41;, "%2.2i&#58;%2.2i&#58;%2.2i", h, m, s&#41;;
		printf&#40;" length         &#58; %s\n", dest&#41;;
	&#125;
&#125;

void error_callback&#40;const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data&#41;
&#123;
	&#40;void&#41;decoder, &#40;void&#41;client_data;

	printf&#40;" Error&#58; %s\n", FLAC__StreamDecoderErrorStatusString&#91;status&#93;&#41;;
&#125;

/////////////////////////////////////////////////////////////////////////////////////////
//Buffer filling
/////////////////////////////////////////////////////////////////////////////////////////

int fillBuffer&#40;SceSize args, void *argp&#41;
&#123;
	int bytes, bytesRed;
	int fillbuf;

	while&#40;runningFlag&#41;&#123;
		sceKernelWaitSema&#40;bufferEmpty, 1, 0&#41;;
		if &#40;OGG_eos || !runningFlag&#41;
			break;
		bytesRed = 0;
		fillbuf = bufferFlip ? &#40;int&#41;pcmout2 &#58; &#40;int&#41;pcmout1;
		while &#40;bytesRed < OUTPUT_BUFFER && runningFlag && !OGG_eos&#41;
		&#123;
			//bytes = ov_read&#40;&OGG_VorbisFile,&#40;char *&#41;&#40;fillbuf+bytesRed&#41;,OUTPUT_BUFFER-bytesRed,&bitStream&#41;;
			bytes = ov_read&#40;&OGG_VorbisFile,&#40;char *&#41;&#40;fillbuf+bytesRed&#41;,OUTPUT_BUFFER-bytesRed,0,2,1,&bitStream&#41;;
			if &#40;bytes == 0&#41;
			&#123;
				//EOF&#58;
				OGG_eos = 1;
				ov_clear&#40;&OGG_VorbisFile&#41;;
			&#125;
			else if &#40;bytes > 0&#41;
			&#123;
				bytesRed += bytes;
			&#125;
		&#125;
		if &#40;bufferFlip&#41;
			pcmlen2 = bytesRed;
		else
			pcmlen1 = bytesRed;
		sceKernelSignalSema&#40;bufferFull, 1&#41;;
	&#125;
	sceKernelExitDeleteThread&#40;0&#41;;
	return 0;
&#125;

/////////////////////////////////////////////////////////////////////////////////////////
//Audio output
/////////////////////////////////////////////////////////////////////////////////////////

int audioOutput&#40;SceSize args, void *argp&#41;
&#123;
	int playlen;
	char *playbuf;

	while&#40;runningFlag&#41;
	&#123;
		sceKernelWaitSema&#40;bufferFull, 1, 0&#41;;
		if &#40;OGG_eos || !runningFlag&#41;
			break;
		playlen = bufferFlip ? pcmlen1 &#58; pcmlen2;
		playbuf = bufferFlip ? pcmout1 &#58; pcmout2;
		bufferFlip ^= 1;
		sceKernelSignalSema&#40;bufferEmpty, 1&#41;;
		sceAudioSetChannelDataLen&#40;OGG_audio_channel, playlen/4&#41;;
		sceAudioOutputBlocking&#40;OGG_audio_channel, audioVol, playbuf&#41;;
	&#125;
	sceKernelExitDeleteThread&#40;0&#41;;
	return 0;
&#125;

/////////////////////////////////////////////////////////////////////////////////////////
//Main
/////////////////////////////////////////////////////////////////////////////////////////

int main&#40;&#41; &#123;
	char *filename;
	SceCtrlData pad;
	char dest&#91;9&#93;;
	long secs;
	int h;
	int m;
	int s;
	int audioThid;
	vorbis_info *vi;
	FLAC__bool ok = true;
	FLAC__StreamDecoder *decoder = 0;
	FLAC__StreamDecoderInitStatus init_status;

	pspDebugScreenInit&#40;&#41;;
	SetupCallbacks&#40;&#41;;

	//Creates semaphores&#58;
	bufferEmpty = sceKernelCreateSema&#40;"bufferEmpty", 0, 1, 1, 0&#41;;
	bufferFull = sceKernelCreateSema&#40;"bufferFull", 0, 0, 1, 0&#41;;

	pspDebugScreenInit&#40;&#41;;
	pspDebugScreenSetBackColor&#40;0xA0602000&#41;;
	pspDebugScreenSetTextColor&#40;0xffffff00&#41;;

	audioVol = 0x4000; // half max volume

mloop&#58;
	filename = RequestFile&#40;"ms0&#58;/MUSIC/"&#41;;

	pspDebugScreenClear&#40;&#41;;
	pspDebugScreenSetXY&#40;25, 1&#41;;
	printf&#40;"Simple Ogg Player"&#41;;
	pspDebugScreenSetXY&#40;25, 3&#41;;
	printf&#40;"CPU&#58; %i BUS&#58; %i", scePowerGetCpuClockFrequency&#40;&#41;, scePowerGetBusClockFrequency&#40;&#41;&#41;;
	pspDebugScreenSetXY&#40;21, 4&#41;;
	printf&#40;"Press X to stop playback"&#41;;

	printf&#40;"\n\n Playing %s\n\n", filename&#41;;
	sceKernelDelayThread&#40;2*1000*1000&#41;;

	if &#40; !strcmp&#40;&filename&#91;strlen&#40;filename&#41;-3&#93;, "ogg"&#41; &#41;
		goto play_ogg;

// play_flac&#58;
	if&#40;&#40;decoder = FLAC__stream_decoder_new&#40;&#41;&#41; == NULL&#41;
	&#123;
		printf&#40;" Could not make FLAC decoder. FLAC files cannot be played.\n"&#41;;
		sceKernelDelayThread&#40;2*1000*1000&#41;;
		goto mloop;
	&#125;

	&#40;void&#41;FLAC__stream_decoder_set_md5_checking&#40;decoder, true&#41;;

	init_status = FLAC__stream_decoder_init_file&#40;decoder, filename, write_callback, metadata_callback, error_callback, the_file&#41;;
	if&#40;init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK&#41;
	&#123;
		printf&#40;" ERROR&#58; initializing decoder&#58; %s\n", FLAC__StreamDecoderInitStatusString&#91;init_status&#93;&#41;;
		fclose&#40;the_file&#41;;
		sceKernelDelayThread&#40;2*1000*1000&#41;;
		goto mloop;
	&#125;

	memset&#40;pcmout1, 0, OUTPUT_BUFFER&#41;;
	memset&#40;pcmout2, 0, OUTPUT_BUFFER&#41;;
	pcmlen1 = 0;
	pcmlen2 = 0;

	OGG_eos = 0;
	runningFlag = 1;
	sceKernelSignalSema&#40;bufferEmpty, 1&#41;;
	sceKernelSignalSema&#40;bufferFull, 0&#41;;

	//Reserve audio channel&#58;
	OGG_audio_channel = sceAudioChReserve&#40;OGG_audio_channel, OUTPUT_BUFFER/4, PSP_AUDIO_FORMAT_STEREO&#41;;

	//Start audio output thread&#58;
	audioThid = sceKernelCreateThread&#40;"audioOutput", audioOutput, 0x16, 0x1800, PSP_THREAD_ATTR_USER, NULL&#41;;
	if&#40;audioThid < 0&#41;
		sceKernelExitGame&#40;&#41;;
	sceKernelStartThread&#40;audioThid, 0, NULL&#41;;

	ok = FLAC__stream_decoder_process_until_end_of_stream&#40;decoder&#41;;
	printf&#40;" decoding&#58; %s\n", ok ? "succeeded" &#58; "FAILED"&#41;;
	printf&#40;"    state&#58; %s\n", FLAC__StreamDecoderStateString&#91;FLAC__stream_decoder_get_state&#40;decoder&#41;&#93;&#41;;

	FLAC__stream_decoder_delete&#40;decoder&#41;;
	fclose&#40;the_file&#41;;

	runningFlag = 0; // kill the threads
	sceKernelSignalSema&#40;bufferEmpty, 1&#41;;
	sceKernelSignalSema&#40;bufferFull, 1&#41;;
	sceKernelDelayThread&#40;1*1000*1000&#41;;

	//Release channel&#58;
	sceAudioChRelease&#40;OGG_audio_channel&#41;;

	sceKernelDelayThread&#40;1*1000*1000&#41;;
	goto mloop;

play_ogg&#58;
	//Apro il file OGG&#58;
	the_file = fopen&#40;filename, "r"&#41;;
	if &#40;&#40;the_file&#41; != NULL&#41;
		ov_open&#40;the_file, &OGG_VorbisFile, NULL, 0&#41;;
	else
	&#123;
		printf&#40;" Error opening file\n"&#41;;
		sceKernelDelayThread&#40;2*1000*1000&#41;;
		goto mloop;
	&#125;

	//Stampo le informazioni sul file&#58;
	vi = ov_info&#40;&OGG_VorbisFile, -1&#41;;
	printf&#40;" Channels   &#58; %d\n", vi->channels&#41;;
	printf&#40;" Sample rate&#58; %ld Hz\n", vi->rate&#41;;
	printf&#40;" Bitrate    &#58; %ld kBit\n", vi->bitrate_nominal/1000&#41;;

	h = 0;
	m = 0;
	s = 0;
	secs = &#40;long&#41;ov_time_total&#40;&OGG_VorbisFile, -1&#41;/1000;
	h = secs / 3600;
	m = &#40;secs - h * 3600&#41; / 60;
	s = secs - h * 3600 - m * 60;
	snprintf&#40;dest, sizeof&#40;dest&#41;, "%2.2i&#58;%2.2i&#58;%2.2i", h, m, s&#41;;
	printf&#40;" Length	&#58; %s\n", dest&#41;;

	sceKernelDelayThread&#40;2*1000*1000&#41;;

	memset&#40;pcmout1, 0, OUTPUT_BUFFER&#41;;
	memset&#40;pcmout2, 0, OUTPUT_BUFFER&#41;;
	pcmlen1 = 0;
	pcmlen2 = 0;

	OGG_eos = 0;
	runningFlag = 1;
	sceKernelSignalSema&#40;bufferEmpty, 1&#41;;
	sceKernelSignalSema&#40;bufferFull, 0&#41;;

	//Reserve audio channel&#58;
	OGG_audio_channel = sceAudioChReserve&#40;OGG_audio_channel, OUTPUT_BUFFER/4, PSP_AUDIO_FORMAT_STEREO&#41;;

	//Start buffer filling thread&#58;
	int bufferThid = sceKernelCreateThread&#40;"bufferFilling", fillBuffer, 0x12, 0x1800, PSP_THREAD_ATTR_USER, NULL&#41;;
	if&#40;bufferThid < 0&#41;
		sceKernelExitGame&#40;&#41;;
	sceKernelStartThread&#40;bufferThid, 0, NULL&#41;;

	//Start audio output thread&#58;
	audioThid = sceKernelCreateThread&#40;"audioOutput", audioOutput, 0x16, 0x1800, PSP_THREAD_ATTR_USER, NULL&#41;;
	if&#40;audioThid < 0&#41;
		sceKernelExitGame&#40;&#41;;
	sceKernelStartThread&#40;audioThid, 0, NULL&#41;;

	while&#40;runningFlag && !OGG_eos&#41;
	&#123;
		//Print timestring&#58;
		secs = &#40;long&#41; ov_time_tell&#40;&OGG_VorbisFile&#41;/1000;
		h = secs / 3600;
		m = &#40;secs - h * 3600&#41; / 60;
		s = secs - h * 3600 - m * 60;
		snprintf&#40;dest, sizeof&#40;dest&#41;, "%2.2i&#58;%2.2i&#58;%2.2i", h, m, s&#41;;
		pspDebugScreenSetXY&#40;1, 16&#41;;
		printf&#40;"Current    &#58; %s\n", dest&#41;;

		sceCtrlReadBufferPositive&#40;&pad, 1&#41;;
		if&#40;pad.Buttons & PSP_CTRL_CROSS&#41;
			break; // stop playback

		if &#40;pad.Buttons & PSP_CTRL_LTRIGGER&#41;
			if &#40;audioVol > 0&#41;
				audioVol -= 0x0800; // 16 steps on the audio

		if &#40;pad.Buttons & PSP_CTRL_RTRIGGER&#41;
			if &#40;audioVol < 0x8000&#41;
				audioVol += 0x0800; // 16 steps on the audio

		sceKernelDelayThread&#40;100*1000&#41;;
	&#125;

	if &#40;OGG_eos == 1&#41;
		printf&#40;"\n\n End of file\n"&#41;;
	else
		printf&#40;"\n\n Playback stopped\n"&#41;;

	runningFlag = 0; // kill the threads
	sceKernelSignalSema&#40;bufferEmpty, 1&#41;;
	sceKernelSignalSema&#40;bufferFull, 1&#41;;
	sceKernelDelayThread&#40;1*1000*1000&#41;;

	//Release channel&#58;
	sceAudioChRelease&#40;OGG_audio_channel&#41;;

	goto mloop;

	return 0; // never reaches here - just supresses compiler warning
&#125;
reqfile.c

Code: Select all

#include <pspkernel.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>


#define printf pspDebugScreenPrintf


#define MAXFILES 1000
#define PAGESIZE 32


static struct fileentries &#123;
	char filename&#91;FILENAME_MAX&#93;;
	char path&#91;FILENAME_MAX&#93;;
	int flags;
&#125; cdfiles&#91;MAXFILES&#93;;

static int maxfiles;


/****************************************************************************
 * get_buttons
 *
 ****************************************************************************/

static unsigned int get_buttons&#40;&#41;
&#123;
	SceCtrlData pad;

	sceCtrlReadBufferPositive&#40;&pad, 1&#41;;
	return pad.Buttons;
&#125;

/****************************************************************************
 * ParseDirectory
 *
 * Parse the directory, returning the number of files found
 ****************************************************************************/

int parse_dir &#40;char *path&#41;
&#123;
	DIR *dir;
	DIR *test_dir;
	struct dirent *dirent = 0;
	struct stat fstat;
	char file_name&#91;FILENAME_MAX&#93;;
	FILE *file;

	maxfiles = 0;
	/* open directory */
	if &#40; &#40; dir = opendir&#40; path &#41; &#41; == 0 &#41;
		return 0;

	while &#40; &#40; dirent = readdir&#40; dir &#41; &#41; != 0 &#41;
	&#123;
		if &#40; dirent->d_name&#91;0&#93; == '.' &#41; continue;
		/* get stats */
		sprintf&#40; file_name, "%s/%s", path, dirent->d_name &#41;;
		if &#40; stat&#40; file_name, &fstat &#41; == -1 &#41; continue;
		/* check directory */
		if &#40; S_ISDIR&#40; fstat.st_mode &#41; &#41;
		&#123;
			if &#40; &#40; test_dir = opendir&#40; file_name &#41; &#41; == 0  &#41; continue;
			closedir&#40; test_dir &#41;;
			memset &#40;&cdfiles&#91;maxfiles&#93;, 0, sizeof &#40;struct fileentries&#41;&#41;;
			strncpy&#40;cdfiles&#91;maxfiles&#93;.path, path, FILENAME_MAX&#41;;
			cdfiles&#91;maxfiles&#93;.path&#91;FILENAME_MAX-1&#93; = 0;
			strncpy&#40;cdfiles&#91;maxfiles&#93;.filename, dirent->d_name, FILENAME_MAX&#41;;
			cdfiles&#91;maxfiles&#93;.filename&#91;FILENAME_MAX-1&#93; = 0;
			cdfiles&#91;maxfiles&#93;.flags = 1;
			maxfiles++;
		&#125;
		else
		/* check regular file */
		if &#40; S_ISREG&#40; fstat.st_mode &#41; &#41;
		&#123;
			/* test it */
			if &#40; &#40; file = fopen&#40; file_name, "r" &#41; &#41; == 0 &#41; continue;
			fclose&#40; file &#41;;
			memset &#40;&cdfiles&#91;maxfiles&#93;, 0, sizeof &#40;struct fileentries&#41;&#41;;
			strncpy&#40;cdfiles&#91;maxfiles&#93;.path, path, FILENAME_MAX&#41;;
			cdfiles&#91;maxfiles&#93;.path&#91;FILENAME_MAX-1&#93; = 0;
			strncpy&#40;cdfiles&#91;maxfiles&#93;.filename, dirent->d_name, FILENAME_MAX&#41;;
			cdfiles&#91;maxfiles&#93;.filename&#91;FILENAME_MAX-1&#93; = 0;
			maxfiles++;
		&#125;

		if &#40;maxfiles == MAXFILES&#41;
			break;
	&#125;
	/* close dir */
	closedir&#40; dir &#41;;

	return maxfiles;
&#125;

/****************************************************************************
 * ShowFiles
 *
 * Support function for FileSelector
 ****************************************************************************/

void ShowFiles&#40; int offset, int selection &#41;
&#123;
	int i,j;
	char text&#91;69&#93;;

	pspDebugScreenClear&#40;&#41;;

	j = 0;
	for &#40; i = offset; i < &#40; offset + PAGESIZE &#41; && i < maxfiles ; i++ &#41;
	&#123;
		if &#40; cdfiles&#91;i&#93;.flags &#41;
		&#123;
			strcpy&#40;text,"&#91;"&#41;;
			strncat&#40;text, cdfiles&#91;i&#93;.filename,66&#41;;
			strcat&#40;text,"&#93;"&#41;;
		&#125;
		else
			strncpy&#40;text, cdfiles&#91;i&#93;.filename, 68&#41;;

		text&#91;68&#93;=0;

		pspDebugScreenSetTextColor&#40;j == &#40; selection - offset &#41; ? 0xbbbbbb00 &#58; 0xffffff00&#41;;
		pspDebugScreenSetXY&#40;&#40;68 - strlen&#40;text&#41;&#41; / 2, i - offset + 1&#41;;
		printf&#40;"%s", text&#41;;

		j++;
	&#125;
	pspDebugScreenSetTextColor&#40;0xffffff00&#41;;
&#125;

/****************************************************************************
 * FileSelector
 *
 * Press X to select, O to cancel, and Triangle to go back a level
 ****************************************************************************/

int FileSelector&#40;&#41;
&#123;
	int offset = 0;
	int selection = 0;
	int havefile = 0;
	int redraw = 1;
	unsigned int p = get_buttons&#40;&#41;;

	while &#40; havefile == 0 && !&#40;p & PSP_CTRL_CIRCLE&#41; &#41;
	&#123;
		if &#40; redraw &#41;
			ShowFiles&#40; offset, selection &#41;;
		redraw = 0;

		while &#40;!&#40;p = get_buttons&#40;&#41;&#41;&#41;
			sceKernelDelayThread&#40;10000&#41;;
		while &#40;p == get_buttons&#40;&#41;&#41;
			sceKernelDelayThread&#40;10000&#41;;

		if &#40; p & PSP_CTRL_DOWN &#41;
		&#123;
			selection++;
			if &#40; selection == maxfiles &#41;
				selection = offset = 0;	// wrap around to top

			if &#40; &#40; selection - offset &#41; == PAGESIZE &#41;
				offset += PAGESIZE; // next "page" of entries

			redraw = 1;
		&#125;

		if &#40; p & PSP_CTRL_UP &#41;
		&#123;
			selection--;
			if &#40; selection < 0 &#41;
			&#123;
				selection = maxfiles - 1;
				offset = maxfiles > PAGESIZE ? selection - PAGESIZE + 1 &#58; 0; // wrap around to bottom
			&#125;

			if &#40; selection < offset &#41;
			&#123;
				offset -= PAGESIZE; // previous "page" of entries
				if &#40; offset < 0 &#41;
					offset = 0;
			&#125;

			redraw = 1;
		&#125;

		if &#40; p & PSP_CTRL_RIGHT &#41;
		&#123;
			selection += PAGESIZE;
			if &#40; selection >= maxfiles &#41;
				selection = offset = 0;	// wrap around to top

			if &#40; &#40; selection - offset &#41; >= PAGESIZE &#41;
				offset += PAGESIZE; // next "page" of entries

			redraw = 1;
		&#125;

		if &#40; p & PSP_CTRL_LEFT &#41;
		&#123;
			selection -= PAGESIZE;
			if &#40; selection < 0 &#41;
			&#123;
				selection = maxfiles - 1;
				offset = maxfiles > PAGESIZE ? selection - PAGESIZE + 1 &#58; 0; // wrap around to bottom
			&#125;

			if &#40; selection < offset &#41;
			&#123;
				offset -= PAGESIZE; // previous "page" of entries
				if &#40; offset < 0 &#41;
					offset = 0;
			&#125;

			redraw = 1;
		&#125;

		if &#40; p & PSP_CTRL_CROSS &#41;
		&#123;
			if &#40; cdfiles&#91;selection&#93;.flags &#41;	/*** This is directory ***/
			&#123;
				char fname&#91;FILENAME_MAX+FILENAME_MAX&#93;;

				strncpy&#40;fname, cdfiles&#91;selection&#93;.path, FILENAME_MAX&#41;;
				fname&#91;FILENAME_MAX-1&#93; = 0;
				strncat&#40;fname, cdfiles&#91;selection&#93;.filename, FILENAME_MAX&#41;;
				fname&#91;FILENAME_MAX+FILENAME_MAX-2&#93; = 0;
				strcat&#40;fname, "/"&#41;;
				offset = selection = 0;
				parse_dir&#40;fname&#41;;
			&#125;
			else
				return selection;

			redraw = 1;
		&#125;

		if &#40; p & PSP_CTRL_TRIANGLE &#41;
		&#123;
			char fname&#91;FILENAME_MAX&#93;;
			int pathpos = strlen&#40;cdfiles&#91;1&#93;.path&#41; - 2;

			while &#40;pathpos > 5&#41;
			&#123;
				if &#40;cdfiles&#91;1&#93;.path&#91;pathpos&#93; == '/'&#41; break;
				pathpos--;
			&#125;
			if &#40;pathpos < 5&#41; pathpos = 5; /** handle root case */
			strncpy&#40;fname, cdfiles&#91;1&#93;.path, pathpos+1&#41;;
			fname&#91;pathpos+1&#93; = 0;
			offset = selection = 0;
			parse_dir&#40;fname&#41;;

			redraw = 1;
		&#125;
	&#125;

	return -1; // no file selected
&#125;

/****************************************************************************
 * RequestFile
 *
 * return pointer to filename selected
 ****************************************************************************/

char *RequestFile &#40;char *initialPath&#41;
&#123;
	int selection;
	static char fname&#91;FILENAME_MAX+FILENAME_MAX&#93;;

	if &#40;!parse_dir&#40;initialPath&#41;&#41;
		return 0;

	selection = FileSelector &#40;&#41;;
	if &#40;selection < 0&#41;
		return 0;

	strncpy &#40;fname, cdfiles&#91;selection&#93;.path, FILENAME_MAX&#41;;
	fname&#91;FILENAME_MAX-1&#93; = 0;
	strncat &#40;fname, cdfiles&#91;selection&#93;.filename, FILENAME_MAX&#41;;
	fname&#91;FILENAME_MAX+FILENAME_MAX-1&#93; = 0;

	return fname;
&#125;
And there you have it. FLAC on the PSP.
Viper8896
Posts: 110
Joined: Thu Jan 26, 2006 6:20 pm

Post by Viper8896 »

thanks jf i didn't realize it would be so simple. i think flac and theora libraries should be added to the ps2dev.org svn.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Viper8896 wrote:thanks jf i didn't realize it would be so simple.
Me neither. I just took a quick look at it, tried a few things, then realized all we need was just libFLAC. Turned out to be disgustingly simple.
i think flac and theora libraries should be added to the ps2dev.org svn.
Well, FLAC for certain. I don't know how well the PSP will do with Theora. You'd really need to put a lot of work into PSP optimizations. Couple that with the fact that virtually no one uses Theora and you see it's probably not worth the effort.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Note: you can use libFLAC with tremor if you disable the ogg support. You won't be able to play Ogg-FLAC streams, but native FLAC works fine. That's really all you need for a FLAC player. Just follow the instructions above, but use this for configuring:

Code: Select all

CFLAGS="-ffast-math -fsigned-char -G0" LDFLAGS="-L$&#40;psp-config --pspsdk-path&#41;/lib -lc -lpspuser" ./configure --enable-maintainer-mode --host=psp --prefix=$&#40;psp-config --psp-prefix&#41; --disable-ogg
kundarmah
Posts: 12
Joined: Mon May 18, 2009 1:29 am

Post by kundarmah »

Why is that when I'm installing flac and made the config.sub edit correctly there's an error coming out?

Code: Select all

$ CFLAGS="-ffast-math -fsigned-char -G0" LDFLAGS="-L$&#40;psp-config --pspsdk-path&#41;
/lib -lc -lpspuser" ./configure --enable-maintainer-mode --host=psp --prefix=$&#40;
psp-config --psp-prefix&#41; --with-ogg=$&#40;psp-config --psp-prefix&#41;
configure&#58; WARNING&#58; If you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used.
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $&#40;MAKE&#41;... yes
checking for psp-strip... psp-strip
checking whether to enable maintainer-specific portions of Makefiles... yes
configure&#58; error&#58; cannot run /bin/sh ./config.sub
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Looks like when you edited config.sub, you screwed something up. Better double check it.
kundarmah
Posts: 12
Joined: Mon May 18, 2009 1:29 am

Post by kundarmah »

J.F. wrote:Looks like when you edited config.sub, you screwed something up. Better double check it.

Code: Select all

3 - Edit config.sub: look for

edit:

already installed it TNX.
kundarmah
Posts: 12
Joined: Mon May 18, 2009 1:29 am

Post by kundarmah »

TNX it can play flac files but why cant it play OGG files? Does this support OGG files?
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

kundarmah wrote:TNX it can play flac files but why cant it play OGG files? Does this support OGG files?
If you compile libFLAC with ogg support, you can use libvorbisdec to play ogg files. If you want to use libvorbisidec (tremor) to play ogg, you cannot compile libFLAC with ogg support as the way tremor and flac use the ogg code conflicts.

If you compile flac without ogg support, it just means that flac streams cannot be in ogg containers, but I've never seen flac in ogg containers anyway.
kundarmah
Posts: 12
Joined: Mon May 18, 2009 1:29 am

Post by kundarmah »

J.F. wrote:
kundarmah wrote:TNX it can play flac files but why cant it play OGG files? Does this support OGG files?
If you compile libFLAC with ogg support, you can use libvorbisdec to play ogg files. If you want to use libvorbisidec (tremor) to play ogg, you cannot compile libFLAC with ogg support as the way tremor and flac use the ogg code conflicts.

If you compile flac without ogg support, it just means that flac streams cannot be in ogg containers, but I've never seen flac in ogg containers anyway.
Thanks man! I got it working.
Post Reply