audiothread.cpp
来自「PocketMVP V0.8082503 source for Pocket 的」· C++ 代码 · 共 413 行
CPP
413 行
/***************************************************************************************
*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. *
* *
* The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
* *
* *
****************************************************************************************
* Authors: *
* Marc Dukette *
**************************************************************************************/
#include "stdafx.h"
#include "avidecaps.h"
#include "audiothread.h"
#include "pocketmvp.h"
#define MAX_WRITE 50
#define MP3_BUFFER_SIZE (4096)
char mp3_buffer[8192];
int LastWritten=0;
int LastDone=0;
int Written=0;
int FirstChunk=0;
int currentpos;
#ifdef DECODE_AUDIO
int before;
int after;
extern int max;
#endif
extern videoinfo* vidinfo;
extern HWAVEOUT m_hwo;
extern int totMsTime;
extern __int64 totAudio;
extern int nShouldbe;
extern int tot;
extern HANDLE eventAudio;
extern HANDLE eventNextFrame;
extern HANDLE ha;
extern UserOptions PlayerOptions;
extern reader rd;
extern int br;
extern bool bPaused;
extern bool bEnd;
extern bool EndReached;
extern bool bSkipChunk;
extern pInit Init;
extern pExit Exit;
extern pSeekStart SeekStart;
extern pSeekEnd SeekEnd;
extern pDecompressAudio DecompressAudio;
extern pGetHeaderInfo GetHeaderInfo;
extern void GetDisplayName();
extern bool RawAudio;
extern HWND hWndMain;
unsigned char * PCM_Last=NULL;
int PCM_LastSize;
TCHAR ID3_Title[200];
TCHAR ID3_Artist[200];
TCHAR ID3_Album[200];
HANDLE hGarbage;
DWORD idGarbage;
// This is an example of an exported function.
void PCM_Init(int Equalizer,char* eq)
{
currentpos=0;
PCM_Last=0;
PCM_LastSize=0;
}
// This is an example of an exported function.
void PCM_Exit(void)
{
}
void PCM_SeekStart()
{
currentpos=0;
}
void PCM_SeekEnd()
{
currentpos=0;
}
//static char buffer[40000];
int PCM_GetHeaderInfo(unsigned char * inbuff, int insize, int* Freq, int* ch, int* BitRate,LPTSTR ID3_Title,LPTSTR ID3_Artist,LPTSTR ID3_Album)
{
// *Freq=44100;
*BitRate=vidinfo->a_bits;//128000;
// *ch=2;
*Freq=vidinfo->a_rate;
*ch=vidinfo->a_chans;
return 0;
}
int PCM_DecompressAudio(unsigned char * inbuff, int insize, char *outmemory, int outmemsize, int *done, int* inputpos)
{
if (inbuff)
{
PCM_Last=inbuff;
PCM_LastSize=insize;
*done=0;
return 0;
}
memcpy(outmemory,PCM_Last,PCM_LastSize);
currentpos+=PCM_LastSize;
*inputpos=currentpos;
*done=PCM_LastSize;
return 32768;
}
void CALLBACK WaveProc(
HWAVEOUT hwo,
UINT uMsg,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2 )
{
if( WOM_DONE == uMsg )
{
TCHAR temp[10];
if (vidinfo&&(!vidinfo->AFAP)&&(vidinfo->video_frames)) nShouldbe=(int)(((__int64)(((LPWAVEHDR)dwParam1)->dwUser)*(__int64)tot/totAudio)+1);
// OutputDebugString(_itow(nShouldbe,temp,10));
// OutputDebugString(_T("\r\n"));
SetEvent(eventNextFrame);
LastDone=((LPWAVEHDR)dwParam1)->dwUser;
PostThreadMessage(idGarbage,WM_USER+501,NULL,dwParam1);
// waveOutUnprepareHeader( m_hwo, (LPWAVEHDR)dwParam1, sizeof(WAVEHDR) );
// Written--;
// if (Written==MAX_WRITE) SetEvent(eventAudio);
// delete (void*)dwParam1;
}
}
static void Write(LPWAVEHDR pwh,int cbData,int offset,HANDLE event)
{
if (!offset||(!cbData))
{
delete (void*)pwh;
return;
}
if (Written>MAX_WRITE)
{
WaitForSingleObject(event,INFINITE);
ResetEvent(event);
if (bSkipChunk)
{
bSkipChunk=false;
return;
}
if (bEnd) return;
}
pwh->dwFlags=pwh->dwLoops = 0;
pwh->dwBytesRecorded=pwh->dwBufferLength = cbData;
pwh->dwUser=offset;
waveOutPrepareHeader( m_hwo, pwh, sizeof(WAVEHDR) );
waveOutWrite( m_hwo, pwh, sizeof(WAVEHDR) );
Written++;
LastWritten=offset;
return;
}
DWORD WINAPI GarbageThread(LPVOID lpParameter)
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message==WM_USER+501)
{
waveOutUnprepareHeader( m_hwo, (LPWAVEHDR)msg.lParam, sizeof(WAVEHDR) );
Written--;
if (Written==MAX_WRITE) SetEvent(eventAudio);
delete (void*)msg.lParam;
}
else if (msg.message==WM_QUIT)
{
return 0;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
DWORD WINAPI AudioThread(LPVOID lpParameter)
{
int status=0;
int nFirst=1;
int pos=0;
int played;
LPWAVEHDR pwh;
Written=0;
int nb_read=0;
int Freq;
int ch;
int totPlayed=0;
WAVEFORMATEX m_wfx;
HANDLE eventNextFrame=CreateEvent(NULL,true,false,_T("eventNextFrame"));
HANDLE eventAudioStopped=CreateEvent(NULL,true,false,_T("eventAudioStopped"));
HANDLE eventAudio=CreateEvent(NULL,true,true,_T("eventAudio"));
if (!RawAudio)
{
Init =(pInit)GetProcAddress((HINSTANCE)ha,_T("Init"));
Exit =(pExit)GetProcAddress((HINSTANCE)ha,_T("Exit"));
SeekStart =(pSeekStart)GetProcAddress((HINSTANCE)ha,_T("SeekStart"));
SeekEnd =(pSeekEnd)GetProcAddress((HINSTANCE)ha,_T("SeekEnd"));
DecompressAudio =(pDecompressAudio)GetProcAddress((HINSTANCE)ha,_T("DecompressAudio"));
GetHeaderInfo =(pGetHeaderInfo)GetProcAddress((HINSTANCE)ha,_T("GetHeaderInfo"));
}
else
{
Init =(pInit)PCM_Init;
Exit =(pExit)PCM_Exit;
SeekStart =(pSeekStart)PCM_SeekStart;
SeekEnd =(pSeekEnd)PCM_SeekEnd;
DecompressAudio =(pDecompressAudio)PCM_DecompressAudio;
GetHeaderInfo =(pGetHeaderInfo)PCM_GetHeaderInfo;
}
Freq=0;
Init(PlayerOptions.EnableEQ, PlayerOptions.Eq);
rd.READER_ReadAudio((char *)mp3_buffer,MP3_BUFFER_SIZE);
while((status=GetHeaderInfo(mp3_buffer,MP3_BUFFER_SIZE,&Freq,&ch,&br,ID3_Title,ID3_Artist,ID3_Album))!=0)
{
if (status==32768) status=0;
if (status>0)
{
//status--;
memmove(mp3_buffer,mp3_buffer+(MP3_BUFFER_SIZE-status),status);
}
int nb_read=rd.READER_ReadAudio((char *)mp3_buffer+status,MP3_BUFFER_SIZE-status);
}
//RefreshDisplay();
// memmove(mp3_buffer+1,mp3_buffer,MP3_BUFFER_SIZE-1);
if (!RawAudio) status=MP3_BUFFER_SIZE;
m_wfx.wFormatTag=WAVE_FORMAT_PCM;
m_wfx.nSamplesPerSec=Freq;
m_wfx.nChannels=ch;
m_wfx.wBitsPerSample=16;
m_wfx.nBlockAlign=ch*m_wfx.wBitsPerSample/8;
m_wfx.nAvgBytesPerSec=m_wfx.nBlockAlign*m_wfx.nSamplesPerSec;
m_wfx.cbSize=0;
totAudio=vidinfo->audio_bytes;
if (!br&&(vidinfo->video_frames))
totAudio=((__int64)totMsTime*(__int64)m_wfx.nAvgBytesPerSec)/(__int64)1000;
FirstChunk=1;
MMRESULT mmr;
mmr=waveOutOpen( &m_hwo,
WAVE_MAPPER,
&m_wfx,
(DWORD)WaveProc,
(DWORD)NULL,
CALLBACK_FUNCTION);
if( mmr != MMSYSERR_NOERROR )
{
if (mmr==WAVERR_BADFORMAT)
{
Exit();
Init(PlayerOptions.EnableEQ,0);
switch(Freq)
{
case 48000:
Freq=44100;
break;
default:
Freq=22050;
break;
}
GetHeaderInfo(mp3_buffer,MP3_BUFFER_SIZE-1,&Freq,&ch,&br,ID3_Title,ID3_Artist,ID3_Album);
m_wfx.nSamplesPerSec=Freq;
mmr=waveOutOpen( &m_hwo,
WAVE_MAPPER,
&m_wfx,
(DWORD)WaveProc,
(DWORD)NULL,
CALLBACK_FUNCTION);
}
else
{
MessageBox(0,_T("Error in Audio"),_T("Wave Open Error"),MB_OK);
return 0;
}
}
hGarbage=CreateThread(NULL,NULL,GarbageThread,(void*)NULL,NULL,&idGarbage);
vidinfo->a_chans=ch;
vidinfo->a_rate=Freq;
GetDisplayName();
if (!lpParameter) waveOutPause(m_hwo);
#ifdef DECODE_AUDIO
before=0;
#endif
do
{
SetEvent(eventNextFrame);
if (status==32768) status=0;
if (status>0)
{
//status--;
memmove(mp3_buffer,mp3_buffer+(MP3_BUFFER_SIZE-status),status);
}
int nb_read=0;
if (MP3_BUFFER_SIZE-status)
{
nb_read=rd.READER_ReadAudio((char *)mp3_buffer+status,MP3_BUFFER_SIZE-status);
if (!nb_read)
{
status=-1;
continue;
}
}
pwh = (LPWAVEHDR) new BYTE[ sizeof( WAVEHDR ) + 8192 ];
pwh->lpData = (LPSTR) &pwh[1];
#ifdef DECODE_AUDIO
// if (before)
// {
// after=GetTickCount()-before;
// //if (after>30)
// max++;
// }
// before=GetTickCount();
#endif
status=DecompressAudio(mp3_buffer,nb_read+status,pwh->lpData,4800,&played,&pos) ;
totPlayed+=played;
#ifndef DECODE_AUDIO
if (br>0||(!vidinfo->video_frames))
Write(pwh,played,pos,eventAudio);
else
Write(pwh,played,totPlayed,eventAudio);
#else
delete pwh;
#endif
if (!status)
{
do
{
if (!bPaused)
{
pwh = (LPWAVEHDR) new BYTE[ sizeof( WAVEHDR ) + 8192 ];
pwh->lpData = (LPSTR) &pwh[1];
#ifdef DECODE_AUDIO
// before=GetTickCount();
#endif
status=DecompressAudio(NULL,0,pwh->lpData,4800,&played,&pos) ;
#ifdef DECODE_AUDIO
// after=GetTickCount()-before;
// if (after>max) max=after;
#endif
if (FirstChunk&&(played))
{
played=0;
FirstChunk=0;
}
totPlayed+=played;
#ifndef DECODE_AUDIO
if (br>0||(!vidinfo->video_frames))
Write(pwh,played,pos,eventAudio);
else
Write(pwh,played,totPlayed,eventAudio);
#else
delete pwh;
#endif
}
else
{
status = 0;
Sleep(1);
}
}while ((!status)&&(!bEnd));
}
} while ((status > 0)&&(!bEnd)&&(status!=MP3_BUFFER_SIZE));
#ifndef DECODE_AUDIO
waveOutRestart(m_hwo);
if (!bEnd)
{
while (LastWritten!=LastDone) Sleep(10);
}
else
{
waveOutReset(m_hwo);
}
#endif
waveOutClose(m_hwo);
PostThreadMessage(idGarbage,WM_QUIT,NULL,NULL);
Exit();
Init=NULL;
if (!bEnd) EndReached=true;
bEnd=1;
SetEvent(eventNextFrame);
SetEvent(eventAudioStopped);
CloseHandle(eventNextFrame);
CloseHandle(eventAudioStopped);
CloseHandle(eventAudio);
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?