libogg / libvorbis

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

Moderators: cheriff, TyRaNiD

Post Reply
hardfalcon
Posts: 5
Joined: Sun Aug 19, 2007 7:41 am

libogg / libvorbis

Post by hardfalcon »

Hi, I got two questions about libogg / libvorbis:
1.) Where can I find a documentation about the functions, constants, etc these 2 libs provide?
2.) Is there any simple sample code playing ogg-vorbis files on the PSP? I know about some programs which play ogg files, but I haven't found any source code so far... :/

Another thing is that I experienced problems while trying to compile libogg (checked out from via svn last night). It kept stating I hadn't installed automake though I actually hae installed automake 1.10 (according to the README.PSP, version 1.6 or above is required). I finally compiled it by changing autogen.sh so that it wouldn't check for autogen and aclocale anymore...

<edit>
I'm NOT using Cygwin but native Linux (Frugalware 0.7-pre2).
</edit>

thx in advance
Pascal
Viper8896
Posts: 110
Joined: Thu Jan 26, 2006 6:20 pm

Post by Viper8896 »

The official web site has docs I've made a simple player that plays a .ogg vorbis file including pausing, showing the current time in seconds of the track and skipping forward and back but the code is written using SDL not native vorbis but here it is anyway.

Code: Select all

/*
 * OGG PLAYER
 *
 *
 */

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <psppower.h>
#include <pspctrl.h>
#include <pspiofilemgr.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pspumd.h>
#include <SDL.h>
#include <SDL_main.h>
#include <SDL_thread.h>
#include <SDL_mixer.h>
#include <psprtc.h>
#include <vorbis/vorbisfile.h>

/* to make typing easier */
#define printf pspDebugScreenPrintf

/* known file types */
#define file1 8557
#define file2 8630
#define file3 8703
#define dire1 4461
#define dire2 4607
#define specialfile 511

/* Screen resolution */
#define W 480
#define H 272

int menu = 0; //menu options
int i = 0; //used for loops
SceCtrlData pad; //stores which button has been pressed
int x = 22; //character that changes while music is playing&#58; /-\|
char nowplaying&#91;256&#93; = ""; //actuall string of currently playing music file
int playthid; //used for playing thread

/* 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, 0, 0&#41;;
	if&#40;thid >= 0&#41;
	&#123;
		sceKernelStartThread&#40;thid, 0, 0&#41;;
	&#125;

	return thid;
&#125;

int goupdirectory&#40;char location&#91;256&#93;&#41;
&#123;
	for&#40;i=0; i<=256; i++&#41;
	&#123;
		if&#40;location&#91;i&#93; == '\0'&#41; //find the first null character
			&#123;
			i --; //go back one character
			location&#91;i&#93; = '\0'; //take of the ending '/'
			/* keep removing charcters until a '/' is found */
			while&#40;location&#91;i&#93; != '/'&#41;
			&#123;
				/* if a '&#58;' is found its gone too far eg&#58; 'ms0&#58;/' */
				if&#40;location&#91;i&#93; == '&#58;'&#41;
				&#123;
					i++;
					location&#91;i&#93; = '/'; //add on a '/'
					i++;
					location&#91;i&#93; = '\0'; // add on the null character
					return 1;
				&#125;
				location&#91;i&#93; = '\0';
				i--;
			&#125;
			return 0;
		&#125;
	&#125;
	return 1;
&#125;

int checkextension&#40;char filename&#91;256&#93;&#41;
&#123;
	for&#40;i=0; i<=255; i++&#41;
	&#123;
		if&#40;filename&#91;i&#93; == '\0'&#41; //find the first null character
		&#123;
			i--;
			if&#40;&#40;filename&#91;i&#93; == 71&#41; || &#40;filename&#91;i&#93; == 103&#41;&#41; //should end in g or G
				&#123;
				i--;
				if&#40;&#40;filename&#91;i&#93; == 71&#41; || &#40;filename&#91;i&#93; == 103&#41;&#41; /*and another g
				or G before that */
				&#123;
					i--;
					if&#40;&#40;filename&#91;i&#93; == 79&#41; || &#40;filename&#91;i&#93; == 111&#41;&#41; /*and o or O before that */
					&#123;
						i--;
						if&#40;filename&#91;i&#93; == 46&#41; //and finally a dot
						&#123;
							return 1; //return 1 for .ogg &#40;will add further extensions such as mp3 in future&#41;
						&#125;
						else
						&#123;
							break; //no dot before ogg so its of the wrong type
						&#125;
					&#125;
					else
					&#123;
						break; //no o before gg so its of the wrong type
					&#125;
				&#125;
				else
				&#123;
					break; //ends in a g but there isnt another g before it
				&#125;
			&#125;
			else
			&#123;
				break; //doesnt end in g so wrong file type
			&#125;
		&#125;
	&#125;
	return 0; //not a playable file
&#125;

int playing&#40;&#41; //thread to run when being played
&#123;
	int k;
	while&#40;1&#41;
	&#123;
		if&#40;Mix_PlayingMusic&#40;&#41; && !Mix_PausedMusic&#40;&#41;&#41; //if its playing and not paused
		&#123;
			switch&#40;x&#41; //this is the spinning character to show music is being played
			&#123;
				case 22&#58;
					x=29;
					break;
				case 23&#58;
					x=30;
					break;
				case 29&#58;
					x=23;
					break;
				case 30&#58;
					x=22;
					break;
			&#125;
		&#125;
		if&#40;Mix_PlayingMusic&#40;&#41; && Mix_PausedMusic&#40;&#41;&#41; //if it is playing but paused
		&#123;
		&#125;
		if&#40;!Mix_PlayingMusic&#40;&#41;&#41; //if not playing
		&#123;
			sceKernelExitDeleteThread&#40;0&#41;;
		&#125;
		/* this loop slows the thread down for controlling the speed of the spinning character */
		for&#40;k=0;k<10;k++&#41;
		&#123;
			sceDisplayWaitVblankStart&#40;&#41;;
		&#125;
	&#125;
&#125;

int starttheogg&#40;&#41;
&#123;
	/* the next 4 variables are used for opening the audio device */
	int audio_rate = 22050;
	Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
	int audio_channels = 2;
	int audio_buffers = 4096;
	/* Mix_Music actually holds the music information.  */
	Mix_Music *music = NULL;
	/* manually open the ogg vorbis file to see how long it is as not available with SDL_mixer */
	OggVorbis_File ovf;
	/* file pointer must be used with ovfile pointer see above^ */
	FILE *fp;
	/* total length of music file&#40;seconds&#41; */
	int vorbis_time;
	/* ticks per second */
	u32 tickspersecond;
	/* start time&#40;ticks&#41; */
	u64 time1;
	/* end time&#40;ticks&#41; */
	u64 time2;
	/* position in current playing music file&#40;in ticks so must divide by tickspersecond&#41; */
	u64 musicposition;
	/* position to seek to */
	double seekto;

	/* get how many ticks per second for working out position in play stream */
	tickspersecond = sceRtcGetTickResolution&#40;&#41;;
	/* open the file for getting its total time as no function available in SDL_mixer */
	fp=fopen&#40;nowplaying, "r"&#41;;
	ov_open&#40;fp,&ovf,NULL,0&#41;;
	vorbis_time = ov_time_total&#40;&ovf,-1&#41;;
	ov_clear&#40;&ovf&#41;;
 	fclose&#40;fp&#41;;
	/* create the thread that goes when playing &#40;int playing&#40;&#41;&#41; see above for the code^.
	 * first initializing playthid to 0. then calling the create thread function.
	 * giving it the name playing_thread. 0x32 priority. 0xFA0 initial stack size.
	 * 0 attributes. NULL options
	 */
	playthid = 0;
	playthid = sceKernelCreateThread&#40;"playing_thread", playing, 0x32, 0xFA0, 0, NULL&#41;;
	/* start at 0 and work towards end */
	musicposition = 0;
	pspDebugScreenSetXY&#40;0,8&#41;;
	printf&#40;"%-256s", nowplaying&#41;;
	pspDebugScreenSetXY&#40;0,26&#41;;
	printf&#40;"<START>  %c  %-25s\n", 61, "Pause/Resume"&#41;;
	printf&#40;"%c        %c  %-25s\n", -8, 61, "Stop"&#41;;
	printf&#40;"L        %c  %-25s\n", 61, "Rewind to start"&#41;;
	printf&#40;"%c        %c  %-25s\n", -48, 61, "Seek Back"&#41;;
	printf&#40;"%c        %c  %-25s", -49, 61, "Seek Forward"&#41;;
	/* Open the audio device not the music file */
	if&#40;Mix_OpenAudio&#40;audio_rate, audio_format, audio_channels, audio_buffers&#41;&#41;
	&#123;
		return 1;
	&#125;
		
	if&#40;music != NULL&#41; //make sure no music is already loaded
	&#123;
		Mix_HaltMusic&#40;&#41;;
		Mix_FreeMusic&#40;music&#41;;
		music = NULL;
	&#125;
	music = Mix_LoadMUS&#40;nowplaying&#41;;
	if&#40;music == NULL&#41; //music should not be null anymore but if it still null, it failed to load
	&#123;
		return 2;
	&#125;
	if&#40;Mix_PlayMusic&#40;music, 0&#41; == -1&#41; //play music returns 0 on success or -1 on error
	&#123;
		return 3;
	&#125;
	if&#40;playthid>=0&#41; //if thread created ok start it
	&#123;
		sceKernelStartThread&#40;playthid,0,0&#41;;
	&#125;
	if&#40;playthid<0&#41;
	&#123;
		pspDebugScreenClear&#40;&#41;;
		printf&#40;"thread error"&#41;;
		while&#40;1&#41; //just sit here in infinite loop so i can see where the error is
		&#123;
		&#125;
	&#125;
	sceRtcGetCurrentTick&#40;&time1&#41;;
	while&#40;Mix_PlayingMusic&#40;&#41;&#41;
	&#123;
		if&#40;Mix_PausedMusic&#40;&#41;&#41;
		&#123;
			pspDebugScreenSetXY&#40;25,15&#41;;
			printf&#40;"music paused \n"&#41;;
		&#125;
		else
		&#123;
			pspDebugScreenSetXY&#40;25,15&#41;;
			printf&#40;"music playing\n"&#41;;
		&#125;
		for&#40;i=0;i<10;i++&#41;
		&#123;
			sceDisplayWaitVblankStart&#40;&#41;;
		&#125;
		while&#40;1&#41;
		&#123;
			if&#40;!Mix_PlayingMusic&#40;&#41;&#41;
			&#123;
				break;
			&#125;
			pspDebugScreenSetXY&#40;40,15&#41;;
			if&#40;Mix_PausedMusic&#40;&#41;&#41;
			&#123;
				sceRtcGetCurrentTick&#40;&time1&#41;;
			&#125;
			sceRtcGetCurrentTick&#40;&time2&#41;;
			musicposition = musicposition + &#40;time2-time1&#41;;
			printf&#40;"%c  %d/%d          ",x,&#40;int&#41;&#40;musicposition/tickspersecond&#41;,vorbis_time&#41;;
			sceRtcGetCurrentTick&#40;&time1&#41;;
			sceCtrlReadBufferPositive&#40;&pad, 1&#41;;
			if&#40;pad.Buttons & PSP_CTRL_LEFT&#41;
			&#123;
				musicposition = musicposition - &#40;tickspersecond*4&#41;;//seek backward 4 seconds
				if&#40;&#40;&#40;int&#41;musicposition&#41;<0&#41;
				&#123;
					musicposition=0;
					sceRtcGetCurrentTick&#40;&time1&#41;;
					seekto = 0;
				&#125;
				else
				&#123;
					seekto = &#40;musicposition/tickspersecond&#41;;
				&#125;
				Mix_SetMusicPosition&#40;seekto&#41;;
				x = 30;
				break;
			&#125;
			if&#40;pad.Buttons & PSP_CTRL_RIGHT&#41;
			&#123;
				musicposition = musicposition + &#40;tickspersecond*4&#41;;//seek forward 4 seconds
				if&#40;&#40;musicposition/tickspersecond&#41;>vorbis_time&#41;
				&#123;
					Mix_HaltMusic&#40;&#41;;
					Mix_FreeMusic&#40;music&#41;;
					music = NULL;
					break;
				&#125;
				seekto = &#40;musicposition/tickspersecond&#41;;
				Mix_SetMusicPosition&#40;seekto&#41;;
				break;
			&#125;
			if&#40;pad.Buttons & PSP_CTRL_START&#41;
			&#123;
				if&#40;Mix_PausedMusic&#40;&#41;&#41;
				&#123;
					Mix_ResumeMusic&#40;&#41;;
					sceRtcGetCurrentTick&#40;&time1&#41;;
				&#125;
				else
				&#123;
					Mix_PauseMusic&#40;&#41;;
				&#125;
				break;
			&#125;
			if&#40;pad.Buttons & PSP_CTRL_CIRCLE&#41;
			&#123;
				Mix_HaltMusic&#40;&#41;;
				Mix_FreeMusic&#40;music&#41;;
				music = NULL;
				break;
			&#125;
			if&#40;pad.Buttons & PSP_CTRL_LTRIGGER&#41;
			&#123;
				x = 30;
				musicposition = 0;
				Mix_RewindMusic&#40;&#41;;
				sceRtcGetCurrentTick&#40;&time1&#41;;
				break;
			&#125;
		&#125;
	&#125;
	pspDebugScreenSetXY&#40;25,15&#41;;
	printf&#40;"%-50c", ' '&#41;;
	return 0;
&#125;

int main&#40;void&#41;
&#123;
	int drive = 0; //used to change drive
	int pos = 0; //file position in current directory
	int dfd; //directory file descriptor
	int morede = 1; //more directory entrys to read
	char location&#91;256&#93; = "fatms0&#58;/"; //location to open
	int filecount = 0; //count how many files in current directory
	int driveneedstochange = 0; //used to check if drive needs to change
	SceIoDirent dir; //store name and info

	memset&#40;&dir, 0, sizeof dir&#41;; //set memory &#40;must do this to make it work&#41;
	SetupCallbacks&#40;&#41;; //setup callbacks
	pspDebugScreenInit&#40;&#41;; //initialize screen
	SDL_Init&#40;SDL_INIT_AUDIO&#41;; //must be called to use sdl audio
	printf&#40;"OGG VORBIS PLAYER\nCoded by Viper"&#41;;
	
	/* Start main loop */
	while&#40;1&#41;
	&#123;
		if&#40;driveneedstochange == 1&#41;
		&#123;
			switch &#40;drive&#41;
			&#123;
				case 0&#58;
					strcpy&#40;location, "fatms0&#58;/"&#41;;
					break;
				case 1&#58;
					pspDebugScreenSetXY&#40;0,8&#41;;
					printf&#40;"%-256s", "Checking UMD..."&#41;;
					i = sceUmdCheckMedium&#40;0&#41;;
					if&#40;i != 0&#41;
					&#123;
						sceUmdActivate&#40;1, "disc0&#58;"&#41;;
						strcpy&#40;location, "disc0&#58;/"&#41;;
						sceUmdWaitDriveStat&#40;UMD_WAITFORINIT&#41;;
						break;
					&#125;
					else
					&#123;
						drive = 2;
					&#125;
				case 2&#58;
					strcpy&#40;location, "flash0&#58;/"&#41;;
					break;
				case 3&#58;
					strcpy&#40;location, "flash1&#58;/"&#41;;
					break;
			&#125;
			driveneedstochange = 0;
		&#125;

		pspDebugScreenSetXY&#40;0,8&#41;;

		if&#40;&#40;dfd = sceIoDopen&#40;location&#41;&#41; >= 0&#41;
		&#123;
			morede = 1;
			filecount = 0;
			while&#40;morede > 0&#41; //while there is more directory entries to read
			&#123;
				morede = sceIoDread&#40;dfd, &dir&#41;;
				filecount ++;
			&#125;
			filecount --;
			sceIoDclose&#40;dfd&#41;;
			dfd = sceIoDopen&#40;location&#41;; //reopening it now that ive got the count
			printf&#40;"%-256s", location&#41;;
			pspDebugScreenSetXY&#40;0,10&#41;;
			for&#40;i = pos; i >= 0; i--&#41;
			&#123;
				morede = sceIoDread&#40;dfd, &dir&#41;;
				if&#40;morede < 0&#41; //error
				&#123;
					printf&#40;"Error reading %-242s", location&#41;; /* it managed to open the directory but couldnt
					read it contents &#40;unlikely going to happen&#41;*/
					while&#40;1&#41;
					&#123;
						sceDisplayWaitVblankStart&#40;&#41;;
					&#125;
				&#125;
			&#125;
			printf&#40;"%d/%-5d", &#40;pos+1&#41;, filecount&#41;;
			pspDebugScreenSetXY&#40;15,10&#41;;
			switch&#40;dir.d_stat.st_mode&#41;
			&#123;
				case dire1&#58;
				case dire2&#58;
					printf&#40;"directory"&#41;;
					break;
				case file1&#58;
				case file2&#58;
				case file3&#58;
					printf&#40;"file     "&#41;;
					break;
				case specialfile&#58;
					printf&#40;"special  "&#41;;
					break;
				default&#58;
					printf&#40;"?&#58;%-7d", dir.d_stat.st_mode&#41;;
					break;
			&#125;
			pspDebugScreenSetXY&#40;25,10&#41;;
			printf&#40;"%-256s", dir.d_name&#41;;

			sceIoDclose&#40;dfd&#41;;
		&#125;

		
		else
		&#123;
			printf&#40;"%-256s", "Error opening drive"&#41;;
		&#125;

		pspDebugScreenSetXY&#40;0,26&#41;;
		printf&#40;"%c        %c  %-25s\n", -40, 61, "Change drive"&#41;; //triangle equals change drive
		printf&#40;"%c        %c  %-25s\n", -8 , 61, "Go up to parent directory"&#41;; //circle equals go up a dir
		printf&#40;"%c        %c  %-25s\n", 28, 61, "Play / enter directory"&#41;; //cross equalls play / enter directory
		printf&#40;"%c/%c      %c  %-25s\n", -50, -51, 61, "Choose file / directory"&#41;; //up/down equals choose file / director
		printf&#40;"%-40c", ' '&#41;;

		for&#40;i = 0; i < 10; i++&#41; //so user cant make accidently press the buttons to quickly
		&#123;
				sceDisplayWaitVblankStart&#40;&#41;;
		&#125;


		/* Start input check loop */
		while&#40;1&#41;
		&#123;
			sceCtrlReadBufferPositive&#40;&pad, 1&#41;;
			if&#40;pad.Buttons & PSP_CTRL_UP&#41;
			&#123;
				if&#40;pos > 0&#41;
				&#123;
					pos--;
					break;
				&#125;
				else
				&#123;
					break;
				&#125;
			&#125;

			if&#40;pad.Buttons & PSP_CTRL_DOWN&#41;
			&#123;
				if&#40;pos < &#40;filecount-1&#41;&#41;
				&#123;
					pos++;
					break;
				&#125;
				else
				&#123;
					break;
				&#125;
			&#125;

			if&#40;pad.Buttons & PSP_CTRL_TRIANGLE&#41;
			&#123;
				pos = 0;
				driveneedstochange = 1;				
				switch &#40;drive&#41;
				&#123;
					case 0&#58;
						drive = 1;
						break;
					case 1&#58;
						drive = 2;
						break;
					case 2&#58;
						drive = 3;
						break;
					case 3&#58;
						drive = 0;
						break;
				&#125;
				
				break;
			&#125;

			if&#40;pad.Buttons & PSP_CTRL_CIRCLE&#41; //when on UMD ther is no .. to go up a dir so we need this
			&#123;
				if&#40;goupdirectory&#40;location&#41; == 0&#41;
				&#123;
					pos = 0;
				&#125;
				break;
			&#125;

			if&#40;pad.Buttons & PSP_CTRL_CROSS&#41; //if ogg play it or if dir change to that dir
			&#123;
				switch&#40;dir.d_stat.st_mode&#41;
				&#123;
					case dire1&#58; //this is to check if its a directory
					case dire2&#58;
						/* do nothing bcos a single dot means the same working dir */
						if&#40;&#40;dir.d_name&#91;0&#93; == '.'&#41; && &#40;dir.d_name&#91;1&#93; == '\0'&#41;&#41;
						&#123;
							break; 
						&#125;
 						/* if we get 2 dots however that means go up a directory */
						if&#40;&#40;dir.d_name&#91;0&#93; == '.'&#41; && &#40;dir.d_name&#91;1&#93; == '.'&#41; && &#40;dir.d_name&#91;2&#93; == '\0'&#41;&#41;
						&#123;
							if&#40;goupdirectory&#40;location&#41; == 0&#41;
							&#123;
								pos = 0;
							&#125;
							break;
						&#125;
						else //must be regular directory
						&#123;
							pos = 0; //start at the first file
							strcat&#40;location, dir.d_name&#41;; //add the directory name to the current location
							for&#40;i=0; i<255; i++&#41;
							&#123;
								if&#40;location&#91;i&#93; == '\0'&#41; //find the first null character
								&#123;
									location&#91;i&#93; = '/'; //and make it a forward slash
									i++;
									location&#91;i&#93; = '\0'; //add the final null character
									break;
								&#125;
							&#125;
						&#125;
						break;
					case file1&#58; //check if file
					case file2&#58;
					case file3&#58;
						//now check if it ends in .ogg
						if&#40;checkextension&#40;dir.d_name&#41; == 1&#41;
						&#123;
							strcpy&#40;nowplaying, location&#41;;
							strcat&#40;nowplaying, dir.d_name&#41;;
							starttheogg&#40;&#41;;
							break;
						&#125;
						break;
					default&#58;
						break; //dont know how to handle this
				&#125;
				break;
			&#125;

		&#125; //end input check loop
		
		morede = 1;

	&#125; //end main loop


	return 0;
&#125; //end main function


This should compile if you have installed the psp toolchain along with the psp ports of libogg libvorbis and libsdl.
kundarmah
Posts: 12
Joined: Mon May 18, 2009 1:29 am

Post by kundarmah »

what's the Makefile for this?
Post Reply