Skip to content

Commit 0883a5b

Browse files
committed
Handle channel selection
1 parent 88af567 commit 0883a5b

2 files changed

Lines changed: 121 additions & 10 deletions

File tree

src/portaudiosound.cpp

Lines changed: 103 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ CSound::CSound( void (*fpNewProcessCallback) ( CVector<short>& psData,
5050
const QString& ) :
5151
CSoundBase ( "portaudio", fpNewProcessCallback, arg, strMIDISetup ),
5252
deviceIndex (-1),
53-
deviceStream (NULL)
53+
deviceStream (NULL),
54+
vSelectedInputChannels ( NUM_IN_OUT_CHANNELS ),
55+
vSelectedOutputChannels ( NUM_IN_OUT_CHANNELS )
5456
{
5557
pThisSound = this;
5658

@@ -136,7 +138,7 @@ int CSound::Init ( const int iNewPrefMonoBufferSize )
136138
iPrefMonoBufferSize = iNewPrefMonoBufferSize;
137139
}
138140

139-
vecsAudioData.Init ( iPrefMonoBufferSize * 2 );
141+
vecsAudioData.Init ( iPrefMonoBufferSize * NUM_IN_OUT_CHANNELS );
140142
if ( deviceStream && deviceIndex >= 0 )
141143
{
142144
LoadAndInitializeDriver ( deviceIndex );
@@ -165,6 +167,82 @@ PaDeviceIndex CSound::DeviceIndexFromName (const QString& strDriverName )
165167
return -1;
166168
}
167169

170+
int CSound::GetNumInputChannels()
171+
{
172+
if (deviceIndex >= 0)
173+
{
174+
const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo ( deviceIndex );
175+
return deviceInfo->maxInputChannels;
176+
}
177+
return CSoundBase::GetNumInputChannels();
178+
}
179+
int CSound::GetNumOutputChannels()
180+
{
181+
if (deviceIndex >= 0)
182+
{
183+
const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo ( deviceIndex );
184+
return deviceInfo->maxOutputChannels;
185+
}
186+
return CSoundBase::GetNumOutputChannels();
187+
}
188+
189+
QString CSound::GetInputChannelName ( const int channel )
190+
{
191+
if (deviceIndex >= 0)
192+
{
193+
const char* channelName;
194+
PaError err = PaAsio_GetInputChannelName ( deviceIndex, channel, &channelName );
195+
if ( err == paNoError )
196+
{
197+
return QString ( channelName );
198+
}
199+
}
200+
return CSoundBase::GetInputChannelName ( channel );
201+
}
202+
QString CSound::GetOutputChannelName ( const int channel )
203+
{
204+
if (deviceIndex >= 0)
205+
{
206+
const char* channelName;
207+
PaError err = PaAsio_GetOutputChannelName ( deviceIndex, channel, &channelName );
208+
if ( err == paNoError )
209+
{
210+
return QString ( channelName );
211+
}
212+
}
213+
return CSoundBase::GetOutputChannelName ( channel );
214+
}
215+
216+
void CSound::SetLeftInputChannel ( const int channel )
217+
{
218+
if ( channel < GetNumInputChannels() )
219+
{
220+
vSelectedInputChannels[0] = channel;
221+
}
222+
}
223+
void CSound::SetRightInputChannel ( const int channel )
224+
{
225+
if ( channel < GetNumInputChannels() )
226+
{
227+
vSelectedInputChannels[1] = channel;
228+
}
229+
}
230+
231+
void CSound::SetLeftOutputChannel ( const int channel )
232+
{
233+
if ( channel < GetNumOutputChannels() )
234+
{
235+
vSelectedOutputChannels[0] = channel;
236+
}
237+
}
238+
void CSound::SetRightOutputChannel ( const int channel )
239+
{
240+
if ( channel < GetNumOutputChannels() )
241+
{
242+
vSelectedOutputChannels[1] = channel;
243+
}
244+
}
245+
168246
QString CSound::LoadAndInitializeDriver ( QString strDriverName, bool bOpenDriverSetup )
169247
{
170248
(void) bOpenDriverSetup; // FIXME: respect this
@@ -181,10 +259,11 @@ QString CSound::LoadAndInitializeDriver ( int devIndex )
181259
{
182260
const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo ( devIndex );
183261

184-
if ( deviceInfo->maxInputChannels < 2 || deviceInfo->maxOutputChannels < 2 )
262+
if ( deviceInfo->maxInputChannels < NUM_IN_OUT_CHANNELS ||
263+
deviceInfo->maxOutputChannels < NUM_IN_OUT_CHANNELS )
185264
{
186265
// FIXME: handle mono devices.
187-
return tr ( "Less than 2 channels supported" );
266+
return tr ( "Less than 2 channels not supported" );
188267
}
189268

190269
if ( deviceStream != NULL )
@@ -195,18 +274,30 @@ QString CSound::LoadAndInitializeDriver ( int devIndex )
195274
}
196275

197276
PaStreamParameters paInputParams;
277+
PaAsioStreamInfo asioInputInfo;
198278
paInputParams.device = devIndex;
199-
paInputParams.channelCount = std::min (2, deviceInfo->maxInputChannels);
279+
paInputParams.channelCount = std::min (NUM_IN_OUT_CHANNELS, deviceInfo->maxInputChannels);
200280
paInputParams.sampleFormat = paInt16;
201281
paInputParams.suggestedLatency = deviceInfo->defaultLowInputLatency;
202-
paInputParams.hostApiSpecificStreamInfo = NULL;
282+
paInputParams.hostApiSpecificStreamInfo = &asioInputInfo;
283+
asioInputInfo.size = sizeof asioInputInfo;
284+
asioInputInfo.hostApiType = paASIO;
285+
asioInputInfo.version = 1;
286+
asioInputInfo.flags = paAsioUseChannelSelectors;
287+
asioInputInfo.channelSelectors = &vSelectedInputChannels[0];
203288

204289
PaStreamParameters paOutputParams;
290+
PaAsioStreamInfo asioOutputInfo;
205291
paOutputParams.device = devIndex;
206-
paOutputParams.channelCount = std::min (2, deviceInfo->maxOutputChannels);
292+
paOutputParams.channelCount = std::min (NUM_IN_OUT_CHANNELS, deviceInfo->maxOutputChannels);
207293
paOutputParams.sampleFormat = paInt16;
208294
paOutputParams.suggestedLatency = deviceInfo->defaultLowOutputLatency;
209-
paOutputParams.hostApiSpecificStreamInfo = NULL;
295+
paOutputParams.hostApiSpecificStreamInfo = &asioOutputInfo;
296+
asioOutputInfo.size = sizeof asioOutputInfo;
297+
asioOutputInfo.hostApiType = paASIO;
298+
asioOutputInfo.version = 1;
299+
asioOutputInfo.flags = paAsioUseChannelSelectors;
300+
asioOutputInfo.channelSelectors = &vSelectedOutputChannels[0];
210301

211302
PaError err = Pa_OpenStream ( &deviceStream,
212303
&paInputParams,
@@ -224,6 +315,8 @@ QString CSound::LoadAndInitializeDriver ( int devIndex )
224315
( Pa_GetLastHostErrorInfo () ->errorText );
225316
}
226317

318+
strCurDevName = deviceInfo->name;
319+
227320
deviceIndex = devIndex;
228321
return "";
229322
}
@@ -249,12 +342,12 @@ int CSound::paStreamCallback(const void *input, void *output, unsigned long fram
249342
CVector<int16_t>& vecsAudioData = pSound->vecsAudioData;
250343

251344
// CAPTURE ---------------------------------
252-
memcpy (&vecsAudioData[0], input, sizeof (int16_t) * frameCount * 2);
345+
memcpy (&vecsAudioData[0], input, sizeof (int16_t) * frameCount * NUM_IN_OUT_CHANNELS);
253346

254347
pSound->ProcessCallback ( vecsAudioData );
255348

256349
// PLAYBACK ------------------------------------------------------------
257-
memcpy (output, &vecsAudioData[0], sizeof (int16_t) * frameCount * 2);
350+
memcpy (output, &vecsAudioData[0], sizeof (int16_t) * frameCount * NUM_IN_OUT_CHANNELS);
258351

259352
return paContinue;
260353
}

src/portaudiosound.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
#include <portaudio.h>
4444

45+
#define NUM_IN_OUT_CHANNELS 2 // always stereo
46+
4547
class CSound : public CSoundBase
4648
{
4749
public:
@@ -56,6 +58,20 @@ class CSound : public CSoundBase
5658
virtual void Start ();
5759
virtual void Stop ();
5860

61+
virtual int GetNumInputChannels();
62+
virtual QString GetInputChannelName ( const int );
63+
virtual void SetLeftInputChannel ( const int );
64+
virtual void SetRightInputChannel ( const int );
65+
virtual int GetLeftInputChannel() { return vSelectedInputChannels[0]; }
66+
virtual int GetRightInputChannel() { return vSelectedInputChannels[1]; }
67+
68+
virtual int GetNumOutputChannels();
69+
virtual QString GetOutputChannelName ( const int );
70+
virtual void SetLeftOutputChannel ( const int );
71+
virtual void SetRightOutputChannel ( const int );
72+
virtual int GetLeftOutputChannel() { return vSelectedOutputChannels[0]; }
73+
virtual int GetRightOutputChannel() { return vSelectedOutputChannels[1]; }
74+
5975
#ifdef WIN32
6076
// Portaudio's function for this takes a device index as a parameter. So it
6177
// needs to reopen ASIO in order to get the right driver loaded. Because of
@@ -79,6 +95,8 @@ class CSound : public CSoundBase
7995
PaHostApiIndex asioIndex;
8096
PaDeviceIndex deviceIndex;
8197
PaStream* deviceStream;
98+
CVector<int> vSelectedInputChannels;
99+
CVector<int> vSelectedOutputChannels;
82100
int iPrefMonoBufferSize;
83101
CVector<int16_t> vecsAudioData;
84102
};

0 commit comments

Comments
 (0)