added soundbase class

This commit is contained in:
Volker Fischer 2009-02-22 23:13:59 +00:00
parent c077f6ecf8
commit 3fb2d9ca5e
9 changed files with 233 additions and 112 deletions

View File

@ -18,6 +18,7 @@ llcon_SOURCES = ../src/buffer.cpp \
../src/protocol.cpp \
../src/multicolorled.cpp \
../src/audiomixerboard.cpp \
../src/soundbase.cpp \
sound.cpp \
../src/buffer.h \
../src/global.h \
@ -33,6 +34,7 @@ llcon_SOURCES = ../src/buffer.cpp \
../src/protocol.h \
../src/multicolorled.h \
../src/audiomixerboard.h \
../src/soundbase.h \
../src/llconserverdlg.h \
../src/chatdlg.h \
../src/llconclientdlg.h \

View File

@ -18,9 +18,10 @@
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <qthread.h>
#include <string.h>
#include "util.h"
#include "soundbase.h"
#include "global.h"
#if WITH_SOUND
@ -40,22 +41,25 @@
#define MAX_SND_BUF_IN 200
#define MAX_SND_BUF_OUT 200
/* Classes ********************************************************************/
class CSound
class CSound : public CSoundBase
{
public:
CSound ( const int iNewBufferSizeStereo )
CSound ( const int iNewStereoBufferSize,
void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) :
#if WITH_SOUND
: rhandle ( NULL ), phandle ( NULL ), iCurPeriodSizeIn ( NUM_PERIOD_BLOCKS_IN ),
CSoundBase ( iNewStereoBufferSize, fpNewCallback, arg ), rhandle ( NULL ),
phandle ( NULL ), iCurPeriodSizeIn ( NUM_PERIOD_BLOCKS_IN ),
iCurPeriodSizeOut ( NUM_PERIOD_BLOCKS_OUT ), bChangParamIn ( true ),
bChangParamOut ( true )
{
// set internal buffer size for read and write
iBufferSizeIn = iNewBufferSizeStereo / NUM_IN_OUT_CHANNELS; // mono size
iBufferSizeOut = iNewBufferSizeStereo / NUM_IN_OUT_CHANNELS; // mono size
iBufferSizeIn = iNewStereoBufferSize / NUM_IN_OUT_CHANNELS; // mono size
iBufferSizeOut = iNewStereoBufferSize / NUM_IN_OUT_CHANNELS; // mono size
}
#else
{}
CSoundBase ( iNewStereoBufferSize, fpNewCallback, arg ) {}
#endif
virtual ~CSound() { Close(); }
@ -70,10 +74,11 @@ public:
int GetInNumBuf() { return iCurPeriodSizeIn; }
void SetOutNumBuf ( int iNewNum );
int GetOutNumBuf() { return iCurPeriodSizeOut; }
void InitRecording ( const bool bNewBlocking = true );
void InitPlayback ( const bool bNewBlocking = false );
bool Read ( CVector<short>& psData );
bool Write ( CVector<short>& psData );
virtual void InitRecording ( const bool bNewBlocking = true );
virtual void InitPlayback ( const bool bNewBlocking = false );
virtual bool Read ( CVector<short>& psData );
virtual bool Write ( CVector<short>& psData );
void Close();
@ -96,13 +101,12 @@ protected:
int GetInNumBuf() { return 1; }
void SetOutNumBuf ( int iNewNum ) {}
int GetOutNumBuf() { return 1; }
void InitRecording ( const bool bNewBlocking = true ) { printf ( "no sound!" ); }
void InitPlayback ( const bool bNewBlocking = false ) { printf ( "no sound!" ); }
bool Read ( CVector<short>& psData ) { printf ( "no sound!" ); return false; }
bool Write ( CVector<short>& psData ) { printf ( "no sound!" ); return false; }
virtual void InitRecording ( const bool bNewBlocking = true ) { printf ( "no sound!" ); }
virtual void InitPlayback ( const bool bNewBlocking = false ) { printf ( "no sound!" ); }
virtual bool Read ( CVector<short>& psData ) { printf ( "no sound!" ); return false; }
virtual bool Write ( CVector<short>& psData ) { printf ( "no sound!" ); return false; }
void Close() {}
#endif
};
#endif // !defined(_SOUND_H__9518A621345F78_3634567_8C0D_EEBF182CF549__INCLUDED_)

View File

@ -26,10 +26,10 @@
/* Implementation *************************************************************/
CClient::CClient ( const quint16 iPortNumber ) : bRun ( false ),
CClient::CClient ( const quint16 iPortNumber ) :
iSndCrdMonoBlockSizeSam ( MIN_SND_CRD_BLOCK_SIZE_SAMPLES ),
iSndCrdStereoBlockSizeSam ( 2 * MIN_SND_CRD_BLOCK_SIZE_SAMPLES ),
Sound ( MIN_SND_CRD_BLOCK_SIZE_SAMPLES * 2 /* stereo */ ),
Sound ( MIN_SND_CRD_BLOCK_SIZE_SAMPLES * 2 /* stereo */, AudioCallback, this ),
Socket ( &Channel, iPortNumber ),
iAudioInFader ( AUD_FADER_IN_MIDDLE ),
iReverbLevel ( 0 ),
@ -173,98 +173,37 @@ void CClient::OnProtocolStatus ( bool bOk )
void CClient::Start()
{
// init object
try
{
Init();
}
catch ( CGenErr generr )
{
// TODO better error management -> should be catched in main thread
// problem: how to catch errors in a different thread...?
// quick hack solution
QMessageBox::critical ( 0, APP_NAME, generr.GetErrorText(), "Quit", 0 );
exit ( 0 );
}
Init();
// enable channel
Channel.SetEnable ( true );
// start the audio working thread with hightest possible priority
start ( QThread::TimeCriticalPriority );
// start audio interface
Sound.Start();
}
void CClient::Stop()
{
// set flag so that thread can leave the main loop
bRun = false;
// give thread some time to terminate
wait ( 5000 );
// disable channel
Channel.SetEnable ( false );
// disable sound interface
Sound.Close();
// stop audio interface
Sound.Stop();
// reset current signal level and LEDs
SignalLevelMeter.Reset();
PostWinMessage ( MS_RESET_ALL, 0 );
}
void CClient::run()
void CClient::AudioCallback ( CVector<short>& psData, void* arg )
{
// Set thread priority (The working thread should have a higher
// priority than the GUI)
#ifdef _WIN32
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
#else
/*
// set the process to realtime privs, taken from
// "http://www.gardena.net/benno/linux/audio" but does not seem to work,
// maybe a problem with user rights
struct sched_param schp;
memset ( &schp, 0, sizeof ( schp ) );
schp.sched_priority = sched_get_priority_max ( SCHED_FIFO );
sched_setscheduler ( 0, SCHED_FIFO, &schp );
*/
#endif
// get the pointer to the object
CClient* pMyClientObj = reinterpret_cast<CClient*> ( arg );
// main loop of working thread
bRun = true;
while ( bRun )
{
// get audio from sound card (blocking function)
if ( Sound.Read ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
}
// process audio data
ProcessAudioData ( vecsAudioSndCrdStereo );
// play the new block
if ( Sound.Write ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
}
}
// process audio data
pMyClientObj->ProcessAudioData ( psData );
}
void CClient::Init()
{
// set block size (in samples)
@ -277,8 +216,7 @@ void CClient::Init()
vecdAudioStereo.Init ( iStereoBlockSizeSam );
Sound.InitRecording();
Sound.InitPlayback();
Sound.Init();
// resample objects are always initialized with the input block size
// record

View File

@ -25,7 +25,7 @@
#if !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ )
#define CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_
#include <qthread.h>
#include <qglobal.h>
#include <qhostaddress.h>
#include <qhostinfo.h>
#include <qstring.h>
@ -58,7 +58,7 @@
/* Classes ********************************************************************/
class CClient : public QThread
class CClient : public QObject
{
Q_OBJECT
@ -68,7 +68,7 @@ public:
void Start();
void Stop();
bool IsRunning() { return bRun; }
bool IsRunning() { return Sound.IsRunning(); }
bool SetServerAddr ( QString strNAddr );
double MicLevelL() { return SignalLevelMeter.MicLevelLeft(); }
double MicLevelR() { return SignalLevelMeter.MicLevelRight(); }
@ -149,8 +149,10 @@ public:
QString strName;
protected:
// callback function must be static, otherwise it does not work
static void AudioCallback ( CVector<short>& psData, void* arg );
void Init();
virtual void run();
void ProcessAudioData ( CVector<short>& vecsStereoSndCrd );
void UpdateTimeResponseMeasurement();
void UpdateSocketBufferSize();
@ -163,7 +165,6 @@ protected:
CSound Sound;
CStereoSignalLevelMeter SignalLevelMeter;
bool bRun;
CVector<double> vecdNetwData;
int iAudioInFader;

98
src/soundbase.cpp Executable file
View File

@ -0,0 +1,98 @@
/******************************************************************************\
* Copyright (c) 2004-2009
*
* Author(s):
* Volker Fischer
*
******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
\******************************************************************************/
#include "soundbase.h"
/* Implementation *************************************************************/
void CSoundBase::Init()
{
InitRecording();
InitPlayback();
}
void CSoundBase::Start()
{
// start the audio thread
start();
}
void CSoundBase::Stop()
{
// set flag so that thread can leave the main loop
bRun = false;
// give thread some time to terminate
wait ( 5000 );
}
void CSoundBase::run()
{
// Set thread priority (The working thread should have a higher
// priority than the GUI)
#ifdef _WIN32
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
#else
/*
// set the process to realtime privs, taken from
// "http://www.gardena.net/benno/linux/audio" but does not seem to work,
// maybe a problem with user rights
struct sched_param schp;
memset ( &schp, 0, sizeof ( schp ) );
schp.sched_priority = sched_get_priority_max ( SCHED_FIFO );
sched_setscheduler ( 0, SCHED_FIFO, &schp );
*/
#endif
// main loop of working thread
bRun = true;
while ( bRun )
{
// TEST
CVector<short> vecsAudioSndCrdStereo ( iStereoBufferSize );
// get audio from sound card (blocking function)
if ( Read ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
}
// process audio data
(*fpCallback) ( vecsAudioSndCrdStereo, pCallbackArg );
// play the new block
if ( Write ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
}
}
}

66
src/soundbase.h Executable file
View File

@ -0,0 +1,66 @@
/******************************************************************************\
* Copyright (c) 2004-2009
*
* Author(s):
* Volker Fischer
*
******************************************************************************
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
\******************************************************************************/
#if !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ )
#define SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_
#include <qthread.h>
#include "global.h"
#include "util.h"
/* Classes ********************************************************************/
class CSoundBase : public QThread
{
public:
CSoundBase ( const int iNewStereoBufferSize,
void (*fpNewCallback) ( CVector<short>& psData, void* arg ),
void* arg ) : iStereoBufferSize ( iNewStereoBufferSize ),
fpCallback ( fpNewCallback ), pCallbackArg ( arg ), bRun ( false ) {}
virtual ~CSoundBase() {}
virtual void Init();
virtual void Start();
virtual void Stop();
bool IsRunning() const { return bRun; }
protected:
// function pointer to callback function
void (*fpCallback) ( CVector<short>& psData, void* arg );
void* pCallbackArg;
// these functions should be overwritten by derived class for
// non callback based audio interfaces
virtual bool Read ( CVector<short>& psData ) { printf ( "no sound!" ); return false; }
virtual bool Write ( CVector<short>& psData ) { printf ( "no sound!" ); return false; }
virtual void InitRecording ( const bool bNewBlocking = true ) = 0;
virtual void InitPlayback ( const bool bNewBlocking = false ) = 0;
void run();
bool bRun;
int iStereoBufferSize;
};
#endif /* !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ ) */

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Version="8.00"
Name="llcon"
ProjectGUID="{DBBC16FC-BBCA-4E3B-A9F4-0EC5202A8B2E}"
RootNamespace="llcon"
@ -571,6 +571,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\src\soundbase.cpp"
>
</File>
<File
RelativePath="..\src\util.cpp"
>
@ -994,6 +998,10 @@
RelativePath="sound.h"
>
</File>
<File
RelativePath="..\src\soundbase.h"
>
</File>
<File
RelativePath="..\src\util.h"
>

View File

@ -681,7 +681,9 @@ void CSound::Close()
bChangParamOut = true;
}
CSound::CSound ( const int iNewBufferSizeStereo )
CSound::CSound ( const int iNewBufferSizeStereo,
void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) :
CSoundBase ( iNewBufferSizeStereo, fpNewCallback, arg )
{
// set internal buffer size value and calculate mono buffer size
iBufferSizeStereo = iNewBufferSizeStereo;

View File

@ -31,6 +31,7 @@
#include <qmessagebox.h>
#include "../src/util.h"
#include "../src/global.h"
#include "../src/soundbase.h"
// copy the ASIO SDK in the llcon/windows directory: "llcon/windows/ASIOSDK2" to
// get it work
@ -51,24 +52,25 @@
/* Classes ********************************************************************/
class CSound
class CSound : public CSoundBase
{
public:
CSound ( const int iNewBufferSizeStereo );
CSound ( const int iNewBufferSizeStereo,
void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg );
virtual ~CSound();
void InitRecording ( const bool bNewBlocking = true )
{
bBlockingRec = bNewBlocking;
InitRecordingAndPlayback();
}
void InitPlayback ( const bool bNewBlocking = false )
{
bBlockingPlay = bNewBlocking;
InitRecordingAndPlayback();
}
bool Read ( CVector<short>& psData );
bool Write ( CVector<short>& psData );
virtual void InitRecording ( const bool bNewBlocking = true )
{
bBlockingRec = bNewBlocking;
InitRecordingAndPlayback();
}
virtual void InitPlayback ( const bool bNewBlocking = false )
{
bBlockingPlay = bNewBlocking;
InitRecordingAndPlayback();
}
virtual bool Read ( CVector<short>& psData );
virtual bool Write ( CVector<short>& psData );
int GetNumDev() { return lNumDevs; }
std::string GetDeviceName ( const int iDiD ) { return cDriverNames[iDiD]; }