now,we can use libaudiocodec and libasfparser to decode wma

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

Moderators: cheriff, TyRaNiD

Post Reply
hrimfaxi
Posts: 20
Joined: Thu Nov 23, 2006 5:40 pm

now,we can use libaudiocodec and libasfparser to decode wma

Post by hrimfaxi »

Hi, folks. I just figure out how to use libaudiocodec and libasfparser to decode wma(asf) format.
This work is done with the help of "cooleyes".

source code download:
[url]http://cooleyes.fx-world.org/downloads/ ... erdemo.rar [/url]
cooleyes
Posts: 123
Joined: Thu May 18, 2006 3:30 pm

Re: now,we can use libaudiocodec and libasfparser to decode

Post by cooleyes »

here is source code

Code: Select all

/* 
 *	Copyright (C) 2009 cooleyes
 *	eyes.cooleyes@gmail.com 
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */
#include <pspkernel.h> 
#include <pspctrl.h> 
#include <pspdisplay.h> 
#include <pspdebug.h> 
#include <psppower.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h>
#include <pspkernel.h> 
#include <pspctrl.h> 
#include <psppower.h> 
#include <pspdebug.h> 
#include <psprtc.h> 
#include <pspsdk.h> 
#include <pspaudiocodec.h> 
#include <pspaudio.h> 
#include <string.h> 
#include <malloc.h> 
#include <psputility.h>
#include "cooleyesBridge.h"
#include "libasfparser/pspasfparser.h"
#include "mem64.h"

int SetupCallbacks&#40;&#41;; 

PSP_MODULE_INFO&#40;"WMA decodeTest", 0, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;;
PSP_HEAP_SIZE_KB&#40;18*1024&#41;;

SceCtrlData input; 

unsigned long wma_codec_buffer&#91;65&#93; __attribute__&#40;&#40;aligned&#40;64&#41;&#41;&#41;;
short wma_mix_buffer&#91;8192&#93; __attribute__&#40;&#40;aligned&#40;64&#41;&#41;&#41;;
short wma_cache_buffer&#91;16384&#93; __attribute__&#40;&#40;aligned&#40;64&#41;&#41;&#41;;
unsigned long wma_cache_samples = 0;

short wma_output_buffer&#91;2&#93;&#91;2048 * 2&#93; __attribute__&#40;&#40;aligned&#40;64&#41;&#41;&#41;;
int wma_output_index = 0;

void* wma_frame_buffer;

SceAsfParser* parser = 0;
ScePVoid need_mem_buffer = 0;


SceUID wma_fd = -1;

u8 wma_getEDRAM = 0;

u16 wma_channels  = 2;
u32 wma_samplerate = 0xAC44;
u16 wma_format_tag = 0x0161;
u32 wma_avg_bytes_per_sec = 3998;
u16 wma_block_align = 1485;
u16 wma_bits_per_sample = 16;
u16 wma_flag = 0x1F;

char filename&#91;1024&#93;;
FILE* dumpfd = 0;

void mesg&#40;const char* fmt, ...&#41; &#123;
	va_list ap;
	char str&#91;1024&#93;;

	va_start&#40;ap, fmt&#41;;
	vsnprintf&#40;str, sizeof&#40;str&#41;, fmt, ap&#41;;
	str&#91;sizeof&#40;str&#41; - 1&#93; = '\0';

	pspDebugScreenPrintf&#40;"%s", str&#41;;
	printf&#40;"%s", str&#41;;

	va_end&#40;ap&#41;;
&#125;

int asf_read_cb&#40;void *userdata, void *buf, SceSize size&#41; &#123;
	
	int ret = sceIoRead&#40;wma_fd, buf, size&#41;;

//	mesg&#40;"%s 0x%08x %d\n", __func__, &#40;u32&#41;buf, size&#41;;

	return ret;
&#125;

SceOff asf_seek_cb&#40;void *userdata, void *buf, SceOff offset, int whence&#41; &#123;

	SceOff ret = -1;

	ret = sceIoLseek&#40;wma_fd, offset, whence&#41;;

//	mesg&#40;"%s@0x%08x 0x%08x %d\n", __func__, ret, offset, whence&#41;;

	return ret;
&#125;


int main&#40;void&#41;
&#123;
	SetupCallbacks&#40;&#41;;
	
	pspDebugScreenInit&#40;&#41;;
	pspDebugScreenSetXY&#40;0, 2&#41;;
	
	int result;
	
	result = sceUtilityLoadAvModule&#40;PSP_AV_MODULE_AVCODEC&#41;; 
	if &#40; result < 0 &#41; &#123;
		pspDebugScreenPrintf&#40;"\nerr&#58; sceUtilityLoadAvModule&#40;PSP_AV_MODULE_AVCODEC&#41;\n"&#41;;
		goto wait;
	&#125;
	
	result = sceUtilityLoadAvModule&#40;PSP_AV_MODULE_ATRAC3PLUS&#41;; 
	if &#40; result < 0 &#41; &#123;
		pspDebugScreenPrintf&#40;"\nerr&#58; sceUtilityLoadAvModule&#40;PSP_AV_MODULE_ATRAC3PLUS&#41;\n"&#41;;
		goto wait;
	&#125;

	SceUID modid;
	int status;
	
	int devkitVersion = sceKernelDevkitVersion&#40;&#41;;
	
	getcwd&#40;filename, 256&#41;;
	
	if &#40; devkitVersion < 0x03050000&#41;
		strcat&#40;filename, "/libasfparser330.prx"&#41;;
	else if &#40; devkitVersion < 0x03070000&#41;
		strcat&#40;filename, "/libasfparser350.prx"&#41;;
	else
		strcat&#40;filename, "/libasfparser370.prx"&#41;;
		
	modid = sceKernelLoadModule&#40;filename, 0, NULL&#41;;
	if&#40;modid >= 0&#41; &#123;
		modid = sceKernelStartModule&#40;modid, 0, 0, &status, NULL&#41;;
		pspDebugScreenPrintf&#40;"\n%s\n", filename&#41;;
	&#125;
	else &#123;
		pspDebugScreenPrintf&#40;"\nerr=0x%08X &#58; sceKernelLoadModule\n", modid&#41;;
		goto wait;
	&#125;
	
	getcwd&#40;filename, 256&#41;;
	strcat&#40;filename, "/cooleyesBridge.prx"&#41;;
	modid = sceKernelLoadModule&#40;filename, 0, NULL&#41;;
	if&#40;modid >= 0&#41; &#123;
		modid = sceKernelStartModule&#40;modid, 0, 0, &status, NULL&#41;;
		pspDebugScreenPrintf&#40;"\n%s\n", filename&#41;;
	&#125;
	else &#123;
		pspDebugScreenPrintf&#40;"\nerr=0x%08X &#58; sceKernelLoadModule&#40;cooleyesBridge&#41;\n", modid&#41;;
		goto wait;
	&#125;
	
	cooleyesMeBootStart&#40;devkitVersion, 3&#41;;
	
	u32 cpu = scePowerGetCpuClockFrequency&#40;&#41;;
	u32 bus = scePowerGetBusClockFrequency&#40;&#41;;
	
	mesg&#40;"cpu=%d, bus=%d\n", cpu, bus&#41;;
	
	if &#40;wma_fd < 0&#41; &#123;
		wma_fd = sceIoOpen&#40;"ms0&#58;/music/Test.wma", PSP_O_RDONLY, 0777&#41;;

		if &#40;wma_fd < 0&#41; &#123;
			mesg&#40;"sceIoOpen&#40;&#41; = 0x%08x\n", wma_fd&#41;;
			goto wait;
		&#125;
	&#125;
		
	int ret;
	
	//sceAsfCheckNeedMem	
	parser = malloc_64&#40;sizeof&#40;SceAsfParser&#41;&#41;;
	if &#40; !parser &#41; &#123;
		mesg&#40;"malloc_64&#40;SceAsfParser&#41; fail"&#41;;
		goto wait;
	&#125;
	memset&#40;parser, 0, sizeof&#40;SceAsfParser&#41;&#41;;
	
	parser->iUnk0 = 0x01;
	parser->iUnk1 = 0x00;
	parser->iUnk2 = 0x000CC003;
	parser->iUnk3 = 0x00;
	parser->iUnk4 = 0x00000000;
	parser->iUnk5 = 0x00000000;
	parser->iUnk6 = 0x00000000;
	parser->iUnk7 = 0x00000000;
	
	ret = sceAsfCheckNeedMem&#40;parser&#41;;
	mesg&#40;"sceAsfCheckNeedMem&#40;&#41; = 0x%08x\n", ret&#41;;
	if &#40; ret < 0 &#41; &#123;
		goto wait;
	&#125;
	
	mesg&#40;"parser->iNeedMem = 0x%08x\n", parser->iNeedMem&#41;;
	
	if &#40; parser->iNeedMem > 0x8000 &#41; &#123;
		mesg&#40;"iNeedMem > 0x8000"&#41;;
		goto wait;
	&#125;
	
	//sceAsfInitParser
	need_mem_buffer = malloc_64&#40;parser->iNeedMem&#41;;
	if &#40; !need_mem_buffer &#41; &#123;
		mesg&#40;"malloc_64&#40;need_mem_buffer&#41; fail"&#41;;
		goto wait;
	&#125;
	
	parser->pNeedMemBuffer = need_mem_buffer;
	parser->iUnk3356 = 0x00000000;
	
	ret = sceAsfInitParser&#40;parser, 0, &asf_read_cb, &asf_seek_cb&#41;;
	mesg&#40;"sceAsfInitParser&#40;&#41; = 0x%08x\n", ret&#41;;
	if &#40; ret < 0 &#41; &#123;
		goto wait;
	&#125;
	wma_channels = *&#40;&#40;u16*&#41;need_mem_buffer&#41;;
	wma_samplerate = *&#40;&#40;u32*&#41;&#40;need_mem_buffer+4&#41;&#41;;
	wma_format_tag = 0x0161;
	wma_avg_bytes_per_sec = *&#40;&#40;u32*&#41;&#40;need_mem_buffer+8&#41;&#41;;
	wma_block_align = *&#40;&#40;u16*&#41;&#40;need_mem_buffer+12&#41;&#41;;
	wma_bits_per_sample = 16;
	wma_flag = *&#40;&#40;u16*&#41;&#40;need_mem_buffer+14&#41;&#41;;
	
	u64 duration = parser->lDuration/100000;
	int hour, minute, second, msecond;
	msecond = duration %100;
	duration /= 100;
	second =  duration % 60;
	duration /= 60;
	minute = duration % 60;
	hour = duration / 60;
	mesg&#40;"Music Duration = %02d&#58;%02d&#58;%02d,%03d\n", hour, minute, second, msecond&#41;;
	
//	dumpfd = fopen&#40;"ms0&#58;/sceAsfInitParser&#40;MEM&#41;.dat", "wb+"&#41;;
//	fwrite&#40;need_mem_buffer, parser->iNeedMem, 1, dumpfd&#41;;
//	fclose&#40;dumpfd&#41;;
	
	memset&#40;wma_codec_buffer, 0, sizeof&#40;wma_codec_buffer&#41;&#41;;
	
	//CheckNeedMem
	wma_codec_buffer&#91;5&#93; = 1;
	ret = sceAudiocodecCheckNeedMem&#40;wma_codec_buffer, 0x1005&#41;;
	mesg&#40;"sceAudiocodecCheckNeedMem=0x%08X\n", ret&#41;;
	if &#40; ret < 0 &#41; &#123;
		goto wait;
	&#125;
	
//	dumpfd = fopen&#40;"ms0&#58;/sceAudiocodecCheckNeedMem1005.dat", "wb+"&#41;;
//	fwrite&#40;wma_codec_buffer, 260, 1, dumpfd&#41;;
//	fclose&#40;dumpfd&#41;;
	
	//GetEDRAM
	ret=sceAudiocodecGetEDRAM&#40;wma_codec_buffer, 0x1005&#41;;
	mesg&#40;"sceAudiocodecGetEDRAM=0x%08X\n", ret&#41;;
	if &#40; ret < 0 &#41; &#123;
		goto wait;
	&#125;
	
//	dumpfd = fopen&#40;"ms0&#58;/sceAudiocodecGetEDRAM1005.dat", "wb+"&#41;;
//	fwrite&#40;wma_codec_buffer, 260, 1, dumpfd&#41;;
//	fclose&#40;dumpfd&#41;;
	
	wma_getEDRAM = 1;
	
	//Init
	u16* p16 = &#40;u16*&#41;&#40;&wma_codec_buffer&#91;10&#93;&#41;;
	p16&#91;0&#93; = wma_format_tag;
	p16&#91;1&#93; = wma_channels;
	wma_codec_buffer&#91;11&#93; = wma_samplerate;
	wma_codec_buffer&#91;12&#93; = wma_avg_bytes_per_sec;
	p16 = &#40;u16*&#41;&#40;&wma_codec_buffer&#91;13&#93;&#41;;
	p16&#91;0&#93; = wma_block_align;
	p16&#91;1&#93; = wma_bits_per_sample;
	p16&#91;2&#93; = wma_flag;
	
	ret=sceAudiocodecInit&#40;wma_codec_buffer, 0x1005&#41;;
	mesg&#40;"sceAudiocodecInit=0x%08X\n", ret&#41;;
	if &#40; ret < 0 &#41; &#123;
		goto wait;
	&#125;
	
//	dumpfd = fopen&#40;"ms0&#58;/sceAudiocodecInit1005.dat", "wb+"&#41;;
//	fwrite&#40;wma_codec_buffer, 260, 1, dumpfd&#41;;
//	fclose&#40;dumpfd&#41;;
	
	wma_frame_buffer = malloc_64&#40;wma_block_align&#41;;
	if &#40;!wma_frame_buffer&#41; &#123;
		mesg&#40;"malloc_64&#40;frame_data_buffer&#41; fail"&#41;;
		goto wait;
	&#125;
	
	int npt = 0 * 1000;

	ret = sceAsfSeekTime&#40;parser, 1, &npt&#41;;
	mesg&#40;"sceAsfSeekTime = 0x%08x\n", ret&#41;;
	if &#40;ret < 0&#41; &#123;	
		goto wait;
	&#125;
	
//	int audio_channel = sceAudioChReserve&#40;0, 2048 , PSP_AUDIO_FORMAT_STEREO&#41;;
	sceAudioSRCChReserve&#40;2048, wma_samplerate, 2&#41;;
	
	memset&#40;wma_cache_buffer, 0, 32768&#41;;
	wma_cache_samples = 0;
	
	while&#40;1&#41; &#123;
		
		if &#40; wma_cache_samples >= 2048 &#41; &#123;
			memcpy&#40;wma_output_buffer&#91;wma_output_index&#93;, wma_cache_buffer, 8192&#41;;
			wma_cache_samples -= 2048;
			if &#40; wma_cache_samples > 0 &#41;
				memmove&#40;wma_cache_buffer, wma_cache_buffer+4096, wma_cache_samples*2*2&#41;;
			sceAudioSRCOutputBlocking&#40;PSP_AUDIO_VOLUME_MAX, wma_output_buffer&#91;wma_output_index&#93;&#41;;
//			sceAudioOutputBlocking&#40;audio_channel, PSP_AUDIO_VOLUME_MAX, wma_output_buffer&#91;wma_output_index&#93;&#41;;
			wma_output_index = &#40;wma_output_index + 1&#41; % 2;	
			continue;
		&#125;
		
		memset&#40;wma_frame_buffer, 0, wma_block_align&#41;;
		parser->sFrame.pData = wma_frame_buffer;
		ret = sceAsfGetFrameData&#40;parser, 1, &parser->sFrame&#41;;
		//mesg&#40;"sceAsfGetFrameData = 0x%08x\n", ret&#41;;
		
		if &#40;ret < 0&#41; &#123;
			break;
		&#125;
		memset&#40;wma_mix_buffer, 0, 16384&#41;;
		
		wma_codec_buffer&#91;6&#93; = &#40;unsigned long&#41;wma_frame_buffer;
		wma_codec_buffer&#91;8&#93; = &#40;unsigned long&#41;wma_mix_buffer;
		wma_codec_buffer&#91;9&#93; = 16384;;
		
		wma_codec_buffer&#91;15&#93; = parser->sFrame.iUnk2;
		wma_codec_buffer&#91;16&#93; = parser->sFrame.iUnk3;
		wma_codec_buffer&#91;17&#93; = parser->sFrame.iUnk5;
		wma_codec_buffer&#91;18&#93; = parser->sFrame.iUnk6;
		wma_codec_buffer&#91;19&#93; = parser->sFrame.iUnk4;
		
		ret = sceAudiocodecDecode&#40;wma_codec_buffer, 0x1005&#41;;
		//mesg&#40;"sceAudiocodecDecode = 0x%08x\n", ret&#41;;
		
		if &#40;ret < 0&#41; &#123;	
			break;
		&#125;
		
		//mesg&#40;"wma_codec_buffer&#91;9&#93; = %d\n", wma_codec_buffer&#91;9&#93;&#41;;
		
		memcpy&#40;wma_cache_buffer+&#40;wma_cache_samples*2&#41;, wma_mix_buffer, wma_codec_buffer&#91;9&#93;&#41;;
		
		wma_cache_samples += &#40;wma_codec_buffer&#91;9&#93;/4&#41;;
		
	&#125;
	
	while&#40;sceAudioOutput2GetRestSample&#40;&#41; > 0&#41;;
	sceAudioSRCChRelease&#40;&#41;;


wait&#58;

	if &#40; wma_getEDRAM &#41; &#123;
		sceAudiocodecReleaseEDRAM&#40;wma_codec_buffer&#41;;
	&#125;
	
	if &#40; !&#40;wma_fd<0&#41; &#41;
		sceIoClose&#40;wma_fd&#41;;

//	if &#40; wma_reader &#41;
//		buffered_reader_close&#40;wma_reader&#41;;
		
	if &#40; parser &#41;
		free_64&#40;parser&#41;;
	if &#40; need_mem_buffer &#41;
		free_64&#40;need_mem_buffer&#41;;
		
	if &#40;wma_frame_buffer&#41;
		free_64&#40;wma_frame_buffer&#41;;
	
	sceCtrlReadBufferPositive&#40;&input, 1&#41;;
	while&#40;!&#40;input.Buttons & PSP_CTRL_TRIANGLE&#41;&#41;
	&#123;
		sceKernelDelayThread&#40;10000&#41;;	// wait 10 milliseconds
		sceCtrlReadBufferPositive&#40;&input, 1&#41;;
	&#125;
	
	sceKernelExitGame&#40;&#41;;
	return 0;
&#125;



/* 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; 
Umin
Posts: 6
Joined: Fri May 08, 2009 11:13 am

Good job!

Post by Umin »

Hi,I'm Umin.
I think it is very helpful for my player.
and here is more thx to you!
this is my frist reply.he he he
BTW:
I'm studying English hard now...
willow :--)
Posts: 107
Joined: Sat Jan 13, 2007 11:50 am

Post by willow :--) »

Thanks!
Post Reply