some more JACK code, this should be a first working version -> not yet tested

This commit is contained in:
Volker Fischer 2009-03-08 21:38:38 +00:00
parent 1697b8f9cd
commit 2fcb37d0e9
3 changed files with 150 additions and 21 deletions

View file

@ -15,7 +15,7 @@
# if USE_JACK # if USE_JACK
CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ),
void* arg ) : void* arg ) :
CSoundBase ( false, fpNewCallback, arg ) CSoundBase ( true, fpNewCallback, arg )
{ {
jack_status_t JackStatus; jack_status_t JackStatus;
@ -29,41 +29,160 @@ CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ),
// tell the JACK server to call "process()" whenever // tell the JACK server to call "process()" whenever
// there is work to be done // there is work to be done
jack_set_process_callback ( pJackClient, process, this ); jack_set_process_callback ( pJackClient, process, this );
// TEST check sample rate, if not correct, just fire error
if ( jack_get_sample_rate ( pJackClient ) != SND_CRD_SAMPLE_RATE )
{
throw CGenErr ( "Jack server sample rate is different from "
"required one" );
} }
// create four ports
input_port_left = jack_port_register ( pJackClient, "input left",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
input_port_right = jack_port_register ( pJackClient, "input right",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
output_port_left = jack_port_register ( pJackClient, "output left",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
output_port_right = jack_port_register ( pJackClient, "output right",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
}
void CSound::Start()
{
const char** ports;
// tell the JACK server that we are ready to roll
if ( jack_activate ( pJackClient ) )
{
throw CGenErr ( "Cannot activate client" );
}
// connect the ports, note: you cannot do this before
// the client is activated, because we cannot allow
// connections to be made to clients that are not
// running
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
JackPortIsPhysical | JackPortIsOutput ) ) == NULL )
{
throw CGenErr ( "Cannot find any physical capture ports" );
}
if ( !ports[1] )
{
throw CGenErr ( "Cannot find enough physical capture ports" );
}
if ( jack_connect ( pJackClient, ports[0], jack_port_name ( input_port_left ) ) )
{
throw CGenErr ( "Cannot connect input ports" );
}
if ( jack_connect ( pJackClient, ports[1], jack_port_name ( input_port_right ) ) )
{
throw CGenErr ( "Cannot connect input ports" );
}
free ( ports );
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
JackPortIsPhysical | JackPortIsInput ) ) == NULL )
{
throw CGenErr ( "Cannot find any physical playback ports" );
}
if ( !ports[1] )
{
throw CGenErr ( "Cannot find enough physical playback ports" );
}
if ( jack_connect ( pJackClient, jack_port_name ( output_port_left ), ports[0] ) )
{
throw CGenErr ( "Cannot connect output ports" );
}
if ( jack_connect ( pJackClient, jack_port_name ( output_port_right ), ports[1] ) )
{
throw CGenErr ( "Cannot connect output ports" );
}
free ( ports );
// call base class
CSoundBase::Start();
}
void CSound::Stop()
{
// deactivate client
jack_deactivate ( pJackClient );
// call base class
CSoundBase::Stop();
}
int CSound::Init ( const int iNewPrefMonoBufferSize ) int CSound::Init ( const int iNewPrefMonoBufferSize )
{ {
// TEST // TEST
return iNewPrefMonoBufferSize; iJACKBufferSizeMono = jack_get_buffer_size ( pJackClient );
// init base clasee
CSoundBase::Init ( iJACKBufferSizeMono );
// set internal buffer size value and calculate stereo buffer size
iJACKBufferSizeStero = 2 * iJACKBufferSizeMono;
// create memory for intermediate audio buffer
vecsTmpAudioSndCrdStereo.Init ( iJACKBufferSizeStero );
// TEST
return iJACKBufferSizeMono;
} }
bool CSound::Read ( CVector<short>& psData )
{
}
bool CSound::Write ( CVector<short>& psData )
{
}
// JACK callbacks -------------------------------------------------------------- // JACK callbacks --------------------------------------------------------------
int CSound::process ( jack_nframes_t nframes, void* arg ) int CSound::process ( jack_nframes_t nframes, void* arg )
{ {
int i;
CSound* pSound = reinterpret_cast<CSound*> ( arg ); CSound* pSound = reinterpret_cast<CSound*> ( arg );
// get input data
jack_default_audio_sample_t* in_left =
(jack_default_audio_sample_t*) jack_port_get_buffer ( pSound->input_port_left, nframes );
jack_default_audio_sample_t* in_right =
(jack_default_audio_sample_t*) jack_port_get_buffer ( pSound->input_port_right, nframes );
// copy input data
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
{
// TODO better conversion from float to short
pSound->vecsTmpAudioSndCrdStereo[2 * i] = (short) in_left[i];
pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = (short) in_right[i];
}
// call processing callback function
pSound->Callback ( pSound->vecsTmpAudioSndCrdStereo );
// put output data
jack_default_audio_sample_t* out_left =
(jack_default_audio_sample_t*) jack_port_get_buffer ( pSound->output_port_left, nframes );
jack_default_audio_sample_t* out_right =
(jack_default_audio_sample_t*) jack_port_get_buffer ( pSound->output_port_right, nframes );
// copy output data
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
{
out_left[i] = pSound->vecsTmpAudioSndCrdStereo[2 * i];
out_right[i] = pSound->vecsTmpAudioSndCrdStereo[2 * i + 1];
}
return 0; // zero on success, non-zero on error return 0; // zero on success, non-zero on error
} }
# else # else
// Wave in ********************************************************************* // Wave in *********************************************************************
void CSound::InitRecording() void CSound::InitRecording()

View file

@ -55,20 +55,30 @@ public:
CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ); CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg );
virtual ~CSound() {} virtual ~CSound() {}
virtual int Init ( const int iNewPrefMonoBufferSize );
virtual void Start();
virtual void Stop();
// not implemented yet, always return one device and default string // not implemented yet, always return one device and default string
int GetNumDev() { return 1; } int GetNumDev() { return 1; }
std::string GetDeviceName ( const int iDiD ) { return "wave mapper"; } std::string GetDeviceName ( const int iDiD ) { return "wave mapper"; }
std::string SetDev ( const int iNewDev ) { return ""; } // dummy std::string SetDev ( const int iNewDev ) { return ""; } // dummy
int GetDev() { return 0; } int GetDev() { return 0; }
virtual int Init ( const int iNewPrefMonoBufferSize ); // these variables should be protected but cannot since we want
virtual bool Read ( CVector<short>& psData ); // to access them from the callback function
virtual bool Write ( CVector<short>& psData ); CVector<short> vecsTmpAudioSndCrdStereo;
int iJACKBufferSizeMono;
int iJACKBufferSizeStero;
jack_port_t* input_port_left;
jack_port_t* input_port_right;
jack_port_t* output_port_left;
jack_port_t* output_port_right;
protected: protected:
// callback // callback
static int process ( jack_nframes_t nframes, void* arg ); static int process ( jack_nframes_t nframes, void* arg );
jack_client_t* pJackClient; jack_client_t* pJackClient;
}; };
# else # else

View file

@ -489,7 +489,7 @@ void CSound::bufferSwitch ( long index, ASIOBool processNow )
} }
// call processing callback function // call processing callback function
pSound->Callback( vecsTmpAudioSndCrdStereo ); pSound->Callback ( vecsTmpAudioSndCrdStereo );
// perform the processing for input and output // perform the processing for input and output
for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) // stereo for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) // stereo