added soundbase class
This commit is contained in:
parent
c077f6ecf8
commit
3fb2d9ca5e
9 changed files with 233 additions and 112 deletions
|
@ -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 \
|
||||
|
|
|
@ -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_)
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
// 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 );
|
||||
}
|
||||
// get the pointer to the object
|
||||
CClient* pMyClientObj = reinterpret_cast<CClient*> ( arg );
|
||||
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
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
|
||||
|
|
11
src/client.h
11
src/client.h
|
@ -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
98
src/soundbase.cpp
Executable 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
66
src/soundbase.h
Executable 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_ ) */
|
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
virtual void InitRecording ( const bool bNewBlocking = true )
|
||||
{
|
||||
bBlockingRec = bNewBlocking;
|
||||
InitRecordingAndPlayback();
|
||||
}
|
||||
void InitPlayback ( const bool bNewBlocking = false )
|
||||
virtual void InitPlayback ( const bool bNewBlocking = false )
|
||||
{
|
||||
bBlockingPlay = bNewBlocking;
|
||||
InitRecordingAndPlayback();
|
||||
}
|
||||
bool Read ( CVector<short>& psData );
|
||||
bool Write ( CVector<short>& psData );
|
||||
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]; }
|
||||
|
|
Loading…
Reference in a new issue