0,0 → 1,718 |
// |
// This file is part of the AC97 mp3 player. |
// (C) copyright Serge 2006 |
// email: infinity_sound@mail.ru |
// |
// 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 of the License, 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. |
|
#include "kolibri.h" |
#include "stdio.h" |
#include "string.h" |
#include "ac97wav.h" |
#include "mp3dec/mp3dec.h" |
|
void thread_proc(); |
void touch(char *buf, int size); |
|
extern char *__argv; |
|
//extern char __path; |
|
/***** for debug output only |
char formats[37][12] = |
{ "PCM_ALL", |
"PCM_2_16_48","PCM_1_16_48","PCM_2_16_44","PCM_1_16_44", |
"PCM_2_16_32","PCM_1_16_32","PCM_2_16_24","PCM_1_16_24", |
"PCM_2_16_22","PCM_1_16_22","PCM_2_16_16","PCM_1_16_16", |
"PCM_2_16_12","PCM_1_16_12","PCM_2_16_11","PCM_1_16_11", |
"PCM_2_16_8","PCM_1_16_8","PCM_2_8_48","PCM_1_8_48", |
"PCM_2_8_44","PCM_1_8_44","PCM_2_8_32","PCM_1_8_32", |
"PCM_2_8_24","PCM_1_8_24","PCM_2_8_22","PCM_1_8_22", |
"PCM_2_8_16","PCM_1_8_16","PCM_2_8_12","PCM_1_8_12", |
"PCM_2_8_11","PCM_1_8_11","PCM_2_8_8","PCM_1_8_8" |
}; |
*******/ |
|
DWORD hDrv; |
DWORD hSound; |
DWORD hBuff; |
DWORD event[2]; |
|
CTRL_INFO info; |
|
FILEINFO fileinfo; |
|
int m_vol; |
DWORD status; |
DWORD offset; |
DWORD first_sync; |
|
char *testbuff; |
char *outbuf; |
char *inpbuf; |
int inpsize; |
int outsize; |
|
char srv_name[] = "INFINITY"; |
char srv_intel[] = "SOUND"; |
char header[] = "AC97 MP3 player"; |
char buttons_text[]=" Play Stop << >> Vol- Vol+"; |
|
MPEG_DECODE_INFO mpginfo; |
MPEG_DECODE_PARAM param; |
|
void (*snd_play)(); |
|
void draw_window() |
{ |
BeginDraw(); |
|
DrawWindow(100,100,299,72,0x404040,3,0,0,0); |
|
make_button(7,24,45,13, 0x10|BT_NORMAL,0x808080); |
make_button(56,24,45,13, 0x11|BT_NORMAL,0x808080); |
make_button(104,24,45,13, 0x12|BT_NORMAL,0x808080); |
make_button(152,24,45,13, 0x13|BT_NORMAL,0x808080); |
make_button(200,24,45,13, 0x14|BT_NORMAL,0x808080); |
make_button(248,24,45,13, 0x15|BT_NORMAL,0x808080); |
|
make_button(7,41,286,11, 0x30|BT_HIDE|BT_NOFRAME,0x404040); |
draw_bar(7,41,286,11,0x404040); |
|
draw_bar(7,55,286,11,0x404040); |
write_text(12,58,0x004000|FONT0, __argv, strlen(__argv)); |
write_text(11,57,0x00FF20|FONT0, __argv, strlen(__argv)); |
|
write_text(8,8,0xFFFFFF|FONT0, header, strlen(header)); |
write_text(12,28,0x404040|FONT0,buttons_text,strlen(buttons_text)); |
write_text(11,27,0xA0FFA0|FONT0,buttons_text,strlen(buttons_text)); |
|
EndDraw(); |
}; |
|
void draw_progress_bar() |
{ DWORD x; |
x = 286.0f * (float)offset/(float)fileinfo.size; |
if(x==0) return; |
draw_bar(7,41,x,11,0xA0A0A0); |
draw_bar(x+7,41,286-x,11,0x404040); |
}; |
|
void debug_out_str(char* str) |
{ |
while (*str != 0) |
{ |
debug_out(*str); |
str++; |
} |
} |
|
int main() //int argc, char *argv[]) |
{ DWORD fmt; |
char *thread_stack; |
DWORD r_bytes; |
int retval; |
|
InitHeap(1024*1024); |
if(get_fileinfo(__argv, &fileinfo)==FILE_NOT_FOUND) |
return 0; |
|
if((hDrv=GetService(srv_intel))==0) |
return 0; |
|
if ((hSound=GetService(srv_name))==0) |
return 0; |
|
GetDevInfo(hDrv, &info); |
|
m_vol = GetMasterVol(hDrv,&m_vol); |
if (m_vol > 85) |
{ m_vol = 85; |
SetMasterVol(hDrv,m_vol); |
}; |
|
_asm {fninit}; |
mp3DecodeInit(); |
|
testbuff = UserAlloc(4096); |
get_fileinfo(__argv, &fileinfo); |
offset = 0; |
retval=read_file (__argv,testbuff,0,2048,&r_bytes); |
if (retval) return 0; |
|
fmt = test_wav((WAVEHEADER*)testbuff); |
if (fmt != 0) |
{ |
snd_play = &play_wave; |
outbuf = UserAlloc(32*1024); |
touch(outbuf, 32768); |
offset = 44; |
} |
else |
{ fmt = test_mp3(testbuff); |
if(fmt ==0) return 0; |
snd_play = &play_mp3; |
|
inpsize = mpginfo.maxInputSize*30; |
inpbuf = UserAlloc(inpsize); |
touch(inpbuf, inpsize); |
outsize = mpginfo.outputSize*30+0x10000; |
outbuf = UserAlloc(outsize); |
touch(outbuf, outsize); |
first_sync = offset; |
}; |
|
status = ST_PLAY; |
|
hBuff = CreateBuffer(hSound,fmt); |
if (hBuff == 0) return 0; |
thread_stack = UserAlloc(4096); |
thread_stack+=4092; |
|
CreateThread(thread_proc, thread_stack); |
|
while(1) |
{ delay(10); |
switch(status) |
{ case ST_PLAY: |
snd_play(); |
continue; |
|
case ST_STOP: |
StopBuffer(hSound, hBuff); |
status = ST_DONE; |
continue; |
|
case ST_EXIT: |
StopBuffer(hSound, hBuff); |
DestroyBuffer(hSound, hBuff); |
return 0; |
}; |
}; |
return 0; |
}; |
|
void touch(char *buf, int size) |
{ int i; |
for ( i = 0;i < size; i+=4096) |
buf[i] = 0; |
}; |
|
DWORD test_mp3(char *buf) |
{ int retval; |
int sync; |
WAVEHEADER whdr; |
DWORD r_bytes=2048; |
|
for (;;) |
{ |
if (!mp3FindSync(buf, 2048, &sync)) |
offset+= 2048; |
else break; |
|
if (offset >= fileinfo.size || offset >= 102400) |
return 0; |
|
retval = read_file (__argv,buf,offset,2048,&r_bytes); |
if(retval != 0) return 0; |
}; |
offset+=sync; |
retval = read_file (__argv,buf,offset,2048,&r_bytes); |
if(retval != 0) return 0; |
|
mp3GetDecodeInfo(buf, r_bytes, &mpginfo, 1); |
whdr.riff_id = 0x46464952; |
whdr.riff_format = 0x45564157; |
whdr.wFormatTag = 0x01; |
whdr.nSamplesPerSec = mpginfo.frequency; |
whdr.nChannels = mpginfo.channels; |
whdr.wBitsPerSample = mpginfo.bitsPerSample; |
|
return test_wav(&whdr); |
}; |
void wave_out(char* buff) |
{ DWORD ev[2]; |
|
GetNotify(&ev[0]); |
SetBuffer(hSound,hBuff,buff,ev[1],0x8000); |
} |
|
void play_mp3() |
{ int retval; |
DWORD r_bytes; |
char *inpPtr; |
char *outPtr; |
int inpBytes; |
int totalout; |
|
offset = first_sync; |
|
retval = read_file (__argv,inpbuf,offset,inpsize,&r_bytes); |
if(retval != 0) |
{ status = ST_STOP; |
return ; |
}; |
offset+=inpsize; |
|
mp3DecodeStart(inpbuf, inpsize); |
|
inpPtr = inpbuf+mpginfo.skipSize; |
inpBytes = inpsize-mpginfo.skipSize; |
outPtr = outbuf; |
totalout=0; |
|
memset(outbuf,0,0x10000); |
SetBuffer(hSound,hBuff,outbuf,0,0x10000); |
PlayBuffer(hSound, hBuff); |
|
_asm { fninit } |
|
while(1) |
{ if(status!=ST_PLAY) |
break; |
|
for(;;) |
{ param.inputBuf = inpPtr; |
param.inputSize = inpBytes; |
param.outputBuf = outPtr; |
|
if(!mp3DecodeFrame(¶m)) |
if( mp3GetLastError()== MP3_ERROR_OUT_OF_BUFFER) |
break; |
|
inpPtr += param.inputSize; |
inpBytes -= param.inputSize; |
outPtr+=param.outputSize; |
totalout+=param.outputSize; |
}; |
memmove(inpbuf, inpPtr, inpBytes); |
retval = read_file(__argv, &inpbuf[inpBytes],offset, inpsize-inpBytes, &r_bytes); |
offset+=r_bytes; |
|
if (r_bytes== 0) break; |
|
inpPtr = inpbuf; |
inpBytes += r_bytes; |
if(totalout < 32768) continue; |
|
outPtr = outbuf; |
while (totalout > 32768) |
{ wave_out(outPtr); |
totalout-=0x8000; |
outPtr+=0x8000; |
}; |
memmove(outbuf,outPtr, totalout); |
outPtr = outbuf+totalout; |
}; |
if(status != ST_EXIT) |
status = ST_STOP; |
}; |
|
void play_wave() |
{ |
int retval; |
int remain; |
int i; |
|
offset = 44; |
|
read_file (__argv,outbuf,offset,32*1024,0); |
offset+=32*1024; |
SetBuffer(hSound,hBuff,outbuf,0,0x8000); |
|
read_file (__argv,outbuf,offset,32*1024,0); |
offset+=32*1024; |
SetBuffer(hSound,hBuff,outbuf,0x8000,0x8000); |
|
PlayBuffer(hSound, hBuff); |
|
retval = 0; |
while(1) |
{ |
if(status!=ST_PLAY) |
break; |
|
GetNotify(&event[0]); |
if(retval == FILE_EOF) |
break; |
remain = fileinfo.size-offset; |
if(remain >=32768) |
{ retval = read_file (__argv,outbuf,offset,32*1024,0); |
offset+=32*1024; |
SetBuffer(hSound,hBuff,outbuf,event[1],0x8000); |
continue; |
}; |
if(remain == 0) |
{ retval = FILE_EOF; |
continue; |
}; |
read_file (__argv,outbuf,offset,remain,0); |
for(i=remain;i<32768;i++) |
outbuf[i] = 0; |
SetBuffer(hSound,hBuff,outbuf,event[1],0x8000); |
retval= FILE_EOF; |
}; |
|
if(status != ST_EXIT) |
status = ST_STOP; |
}; |
|
void snd_stop() |
{ |
StopBuffer(hSound, hBuff); |
}; |
|
void thread_proc() |
{ int evnt; |
int pos; |
int key; |
|
_asm { fninit }; |
|
|
draw_window(); |
|
while(1) |
{ if(status==ST_PLAY) |
{ draw_progress_bar(); |
evnt = wait_for_event(80); |
// debug_out_str("BIG ERROR...\x0D\x0A\x00"); |
} |
else |
evnt = wait_for_event_infinite(); |
|
switch(evnt) |
{ |
case EV_REDRAW: |
draw_window(); |
break; |
|
case EV_KEY: |
key = get_key(); |
if(key==27) |
{ status = ST_EXIT; |
exit(); |
}; |
if((key==45)||key==54) |
{ if(m_vol > 0) |
{ m_vol--; |
SetMasterVol(hDrv,m_vol); |
}; |
break; |
}; |
if((key==61)||key==56) |
{ if(m_vol < 90) |
{ m_vol++; |
SetMasterVol(hDrv,m_vol); |
}; |
}; |
break; |
|
case EV_BUTTON: |
switch(get_button_id()) |
{ case 1: |
status = ST_EXIT; |
exit(); |
break; |
|
case 0x10: |
status = ST_PLAY; |
continue; |
|
case 0x11: |
status = ST_STOP; |
break; |
// case 0x12: |
// case 0x13: |
case 0x14: |
if(m_vol > 0) |
{ m_vol--; |
SetMasterVol(hDrv,m_vol); |
}; |
break; |
|
case 0x15: |
if(m_vol < 90) |
{ m_vol++; |
SetMasterVol(hDrv,m_vol); |
}; |
break; |
|
case 0x30: |
if(status==ST_DONE) |
break; |
if(snd_play == play_mp3) |
continue; |
pos = (GetMousePos(REL_WINDOW)>>16)-7; |
offset = ((fileinfo.size-44)/286*pos+44)&0xFFFFFFFC; |
draw_progress_bar(); |
break; |
}; |
}; |
}; |
}; |
|
DWORD test_wav(WAVEHEADER *hdr) |
{ |
if(hdr->riff_id != 0x46464952) |
return 0; |
|
if(hdr->riff_format != 0x45564157) |
return 0; |
|
if (hdr->wFormatTag != 0x01) |
return 0; |
|
switch(hdr->nSamplesPerSec) |
{ case 48000: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_48; |
else |
return PCM_1_8_48; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_48; |
else |
return PCM_2_8_48; |
}; |
|
case 44100: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_44; |
else |
return PCM_1_8_44; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_44; |
else |
return PCM_2_8_44; |
}; |
|
case 32000: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_32; |
else |
return PCM_1_8_32; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_32; |
else |
return PCM_2_8_32; |
}; |
|
case 24000: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_24; |
else |
return PCM_1_8_24; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_24; |
else |
return PCM_2_8_24; |
}; |
|
case 22050: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_22; |
else |
return PCM_1_8_22; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_22; |
else |
return PCM_2_8_22; |
}; |
|
case 16000: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_16; |
else |
return PCM_1_8_16; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_16; |
else |
return PCM_2_8_16; |
}; |
|
case 12000: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_12; |
else |
return PCM_1_8_12; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_12; |
else |
return PCM_2_8_12; |
}; |
|
case 11025: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_11; |
else |
return PCM_1_8_11; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_11; |
else |
return PCM_2_8_11; |
}; |
|
case 8000: |
switch (hdr->nChannels) |
{ case 1: |
if(hdr->wBitsPerSample == 16) |
return PCM_1_16_8; |
else |
return PCM_1_8_8; |
|
case 2: |
if(hdr->wBitsPerSample == 16) |
return PCM_2_16_8; |
else |
return PCM_2_8_8; |
}; |
default: |
return 0; |
}; |
}; |
|
void delay (int val) |
{ |
_asm |
{ mov eax,5 |
mov ebx, [val] |
int 0x40 |
}; |
} |
|
int wait_for_event(int time) |
{ int retval; |
_asm |
{ mov eax,23 |
mov ebx,[time] |
int 0x40 |
mov [retval], eax |
}; |
return retval; |
}; |
|
int wait_for_event_infinite() |
{ int retval; |
_asm |
{ mov eax,10 |
int 0x40 |
mov [retval], eax |
}; |
return retval; |
}; |
|
void BeginDraw() |
{_asm |
{ mov eax,12 |
mov ebx, 1 |
int 0x40 |
}; |
}; |
|
void EndDraw() |
{ _asm |
{ mov eax,12 |
mov ebx, 2 |
int 0x40 |
}; |
}; |
|
void * __cdecl memmove ( void * dst, const void * src, size_t count) |
{ void * ret = dst; |
|
if (dst <= src || (char *)dst >= ((char *)src + count)) |
{ |
while (count--) |
{ *(char *)dst = *(char *)src; |
dst = (char *)dst + 1; |
src = (char *)src + 1; |
} |
} |
else |
{ |
dst = (char *)dst + count - 1; |
src = (char *)src + count - 1; |
while (count--) |
{ *(char *)dst = *(char *)src; |
dst = (char *)dst - 1; |
src = (char *)src - 1; |
} |
} |
return(ret); |
}; |
|
|
|
|
// debug_out_str(formats[fmt]); |
// debug_out_str("\x0D\x0A\x00"); |
|
// debug_out_str("pci cmd: "); |
// debug_out_hex(info.pci_cmd); |
// debug_out_str("\x0D\x0A\x00"); |
|
// debug_out_str("irq line: "); |
// debug_out_hex(info.irq); |
// debug_out_str("\x0D\x0A\x00"); |
|
// debug_out_str("global control: "); |
// debug_out_hex(info.glob_cntrl); |
// debug_out_str("\x0D\x0A\x00"); |
|
// debug_out_str("global status: "); |
// debug_out_hex(info.glob_sta); |
// debug_out_str("\x0D\x0A\x00"); |
|
|
// call _print_volume |
|
// debug_out_hex(whdr.nChannels); |
// debug_out_str("\x0D\x0A\x00"); |
// debug_out_hex(whdr.nSamplesPerSec); |
// debug_out_str("\x0D\x0A\x00"); |
|
// debug_out_hex(fmt); |
// debug_out_str("\x0D\x0A\x00"); |
|
|
|