You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
7.2 KiB

/*
* Copyright (C) 2006-2009 by Jonathan Naylor G4KLX
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "SoundCardReaderWriter.h"
int scrwCallback(const void* input, void* output, unsigned long nSamples, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData)
{
wxASSERT(userData != NULL);
CSoundCardReaderWriter* object = reinterpret_cast<CSoundCardReaderWriter*>(userData);
object->callback(static_cast<const wxFloat32*>(input), static_cast<wxFloat32*>(output), nSamples);
return paContinue;
}
CSoundCardReaderWriter::CSoundCardReaderWriter(const wxString& readDevice, const wxString& writeDevice, unsigned int sampleRate, unsigned int blockSize) :
m_readDevice(readDevice),
m_writeDevice(writeDevice),
m_sampleRate(sampleRate),
m_blockSize(blockSize),
m_buffer(NULL),
m_stream(NULL),
m_callback(NULL),
m_id(-1)
{
m_buffer = new wxFloat32[blockSize];
}
CSoundCardReaderWriter::~CSoundCardReaderWriter()
{
delete[] m_buffer;
}
wxArrayString CSoundCardReaderWriter::getReadDevices()
{
wxArrayString devices;
devices.Alloc(10);
PaError error = ::Pa_Initialize();
if (error != paNoError)
return devices;
#if defined(__WINDOWS__)
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paDirectSound);
#elif defined(__APPLE__) && defined(__MACH__)
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paCoreAudio);
#else
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paALSA);
#endif
if (apiIndex == paHostApiNotFound) {
::Pa_Terminate();
return devices;
}
PaDeviceIndex n = ::Pa_GetDeviceCount();
if (n <= 0) {
::Pa_Terminate();
return devices;
}
for (PaDeviceIndex i = 0; i < n; i++) {
const PaDeviceInfo* device = ::Pa_GetDeviceInfo(i);
if (device->hostApi != apiIndex)
continue;
if (device->maxInputChannels > 0) {
wxString name(device->name, wxConvLocal);
devices.Add(name);
}
}
::Pa_Terminate();
return devices;
}
wxArrayString CSoundCardReaderWriter::getWriteDevices()
{
wxArrayString devices;
devices.Alloc(10);
PaError error = ::Pa_Initialize();
if (error != paNoError)
return devices;
#if defined(__WINDOWS__)
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paDirectSound);
#elif defined(__APPLE__) && defined(__MACH__)
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paCoreAudio);
#else
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paALSA);
#endif
if (apiIndex == paHostApiNotFound) {
::Pa_Terminate();
return devices;
}
PaDeviceIndex n = ::Pa_GetDeviceCount();
if (n <= 0) {
::Pa_Terminate();
return devices;
}
for (PaDeviceIndex i = 0; i < n; i++) {
const PaDeviceInfo* device = ::Pa_GetDeviceInfo(i);
if (device->hostApi != apiIndex)
continue;
if (device->maxOutputChannels > 0) {
wxString name(device->name, wxConvLocal);
devices.Add(name);
}
}
::Pa_Terminate();
return devices;
}
void CSoundCardReaderWriter::setCallback(IAudioCallback* callback, int id)
{
wxASSERT(callback != NULL);
m_callback = callback;
m_id = id;
}
bool CSoundCardReaderWriter::open()
{
PaError error = ::Pa_Initialize();
if (error != paNoError) {
wxLogError(wxT("Cannot initialise PortAudio"));
return false;
}
PaStreamParameters* pParamsIn = NULL;
PaStreamParameters* pParamsOut = NULL;
PaStreamParameters paramsIn;
PaStreamParameters paramsOut;
PaDeviceIndex inDev, outDev;
bool res = convertNameToDevices(inDev, outDev);
if (!res) {
wxLogError(wxT("Cannot convert name to device"));
return false;
}
if (inDev != -1) {
const PaDeviceInfo* inInfo = ::Pa_GetDeviceInfo(inDev);
if (inInfo == NULL) {
wxLogError(wxT("Cannot get device information for the input device"));
return false;
}
paramsIn.device = inDev;
paramsIn.channelCount = 1;
paramsIn.sampleFormat = paFloat32;
paramsIn.hostApiSpecificStreamInfo = NULL;
paramsIn.suggestedLatency = inInfo->defaultLowInputLatency;
pParamsIn = &paramsIn;
}
if (outDev != -1) {
const PaDeviceInfo* outInfo = ::Pa_GetDeviceInfo(outDev);
if (outInfo == NULL) {
wxLogError(wxT("Cannot get device information for the output device"));
return false;
}
paramsOut.device = outDev;
paramsOut.channelCount = 1;
paramsOut.sampleFormat = paFloat32;
paramsOut.hostApiSpecificStreamInfo = NULL;
paramsOut.suggestedLatency = outInfo->defaultLowOutputLatency;
pParamsOut = &paramsOut;
}
error = ::Pa_OpenStream(&m_stream, pParamsIn, pParamsOut, double(m_sampleRate), m_blockSize, paNoFlag, &scrwCallback, this);
if (error != paNoError) {
wxLogError(wxT("Cannot open the audios stream(s)"));
::Pa_Terminate();
return false;
}
error = ::Pa_StartStream(m_stream);
if (error != paNoError) {
wxLogError(wxT("Cannot start the audio stream(s)"));
::Pa_CloseStream(m_stream);
m_stream = NULL;
::Pa_Terminate();
return false;
}
return true;
}
void CSoundCardReaderWriter::close()
{
wxASSERT(m_stream != NULL);
::Pa_AbortStream(m_stream);
::Pa_CloseStream(m_stream);
::Pa_Terminate();
}
void CSoundCardReaderWriter::callback(const wxFloat32* input, wxFloat32* output, unsigned int nSamples)
{
if (m_callback != NULL)
m_callback->callback(input, output, nSamples, m_id);
}
bool CSoundCardReaderWriter::convertNameToDevices(PaDeviceIndex& inDev, PaDeviceIndex& outDev)
{
inDev = outDev = -1;
#if defined(__WINDOWS__)
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paDirectSound);
#elif defined(__APPLE__) && defined(__MACH__)
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paCoreAudio);
#else
PaHostApiIndex apiIndex = ::Pa_HostApiTypeIdToHostApiIndex(paALSA);
#endif
if (apiIndex == paHostApiNotFound)
return false;
PaDeviceIndex n = ::Pa_GetDeviceCount();
if (n <= 0)
return false;
for (PaDeviceIndex i = 0; i < n; i++) {
const PaDeviceInfo* device = ::Pa_GetDeviceInfo(i);
if (device->hostApi != apiIndex)
continue;
wxString name(device->name, wxConvLocal);
if (!m_readDevice.IsEmpty() && m_readDevice.IsSameAs(name) && device->maxInputChannels > 0)
inDev = i;
if (!m_writeDevice.IsEmpty() && m_writeDevice.IsSameAs(name) && device->maxOutputChannels > 0)
outDev = i;
}
if (inDev == -1 && outDev == -1)
return false;
return true;
}

Powered by TurnKey Linux.