mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-02-03 09:44:26 -05:00
Revert "switch from portaudio -> libao"
This reverts commit 8972e87765
.
This commit is contained in:
parent
28afe9d3be
commit
f6f4c3c057
@ -62,6 +62,10 @@ if (DEFINED WIN32)
|
||||
include_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll64 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release )
|
||||
link_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll64 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/x64 )
|
||||
set(FFTW_LIB fftw3-3)
|
||||
|
||||
include_directories ( ${PROJECT_SOURCE_DIR}/external/portaudio/include )
|
||||
link_directories ( ${PROJECT_SOURCE_DIR}/external/portaudio/libs )
|
||||
SET (PORTAUDIO_LIBRARY portaudio.dll winmm)
|
||||
|
||||
link_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/lib/64 )
|
||||
include_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/include )
|
||||
@ -73,6 +77,7 @@ else (DEFINED WIN32)
|
||||
|
||||
set(FFTW_LIB fftw3)
|
||||
|
||||
SET (PORTAUDIO_LIBRARY portaudio)
|
||||
endif (DEFINED WIN32)
|
||||
|
||||
|
||||
@ -143,7 +148,7 @@ ADD_DEFINITIONS(
|
||||
|
||||
add_executable(CubicSDR ${cubicsdr_sources} ${cubicsdr_headers})
|
||||
|
||||
target_link_libraries(CubicSDR rtlsdr liquid ao ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES})
|
||||
target_link_libraries(CubicSDR rtlsdr liquid ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${PORTAUDIO_LIBRARY})
|
||||
# cubicvr2 glfw ${GLFW_LIBRARIES}
|
||||
|
||||
|
||||
|
@ -2,70 +2,165 @@
|
||||
#include "CubicSDRDefs.h"
|
||||
#include <vector>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
|
||||
// trim from start
|
||||
static inline std::wstring &wltrim(std::wstring &s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from end
|
||||
static inline std::wstring &wrtrim(std::wstring &s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from both ends
|
||||
static inline std::wstring &wtrim(std::wstring &s) {
|
||||
return wltrim(wrtrim(s));
|
||||
}
|
||||
#endif
|
||||
|
||||
//wxDEFINE_EVENT(wxEVT_COMMAND_AudioThread_INPUT, wxThreadEvent);
|
||||
|
||||
AudioThread::AudioThread(AudioThreadQueue* pQueue, int id) :
|
||||
wxThread(wxTHREAD_DETACHED), m_pQueue(pQueue), m_ID(id), audio_queue_ptr(
|
||||
0) { //, stream(NULL)
|
||||
wxThread(wxTHREAD_DETACHED), m_pQueue(pQueue), m_ID(id), audio_queue_ptr(0), stream(NULL) {
|
||||
|
||||
}
|
||||
AudioThread::~AudioThread() {
|
||||
ao_close(device);
|
||||
ao_shutdown();
|
||||
PaError err;
|
||||
err = Pa_StopStream(stream);
|
||||
err = Pa_CloseStream(stream);
|
||||
Pa_Terminate();
|
||||
}
|
||||
|
||||
|
||||
static int audioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags, void *userData) {
|
||||
|
||||
AudioThread *src = (AudioThread *) userData;
|
||||
|
||||
float *out = (float*) outputBuffer;
|
||||
|
||||
if (statusFlags & paOutputOverflow) {
|
||||
std::cout << "Audio buffer overflow.." << std::endl;
|
||||
}
|
||||
|
||||
if (statusFlags & paOutputUnderflow) {
|
||||
std::cout << "Audio buffer underflow.." << std::endl;
|
||||
}
|
||||
|
||||
if ((statusFlags & paPrimingOutput) || (statusFlags & paOutputOverflow) || !src->audio_queue.size()) {
|
||||
for (int i = 0; i < framesPerBuffer * 2; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
std::vector<float> nextBuffer = src->audio_queue.front();
|
||||
|
||||
for (int i = 0; i < framesPerBuffer * 2; i++) {
|
||||
out[i] = nextBuffer[src->audio_queue_ptr];
|
||||
|
||||
src->audio_queue_ptr++;
|
||||
|
||||
if (src->audio_queue_ptr == nextBuffer.size()) {
|
||||
src->audio_queue.pop();
|
||||
src->audio_queue_ptr = 0;
|
||||
if (!src->audio_queue.size()) {
|
||||
break;
|
||||
}
|
||||
nextBuffer = src->audio_queue.front();
|
||||
}
|
||||
}
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
|
||||
wxThread::ExitCode AudioThread::Entry() {
|
||||
|
||||
ao_initialize();
|
||||
PaError err;
|
||||
err = Pa_Initialize();
|
||||
if (err != paNoError) {
|
||||
std::cout << "Error starting :(\n";
|
||||
return (wxThread::ExitCode) 1;
|
||||
}
|
||||
|
||||
/* -- Setup for default driver -- */
|
||||
int preferred_device = -1;
|
||||
|
||||
int default_driver;
|
||||
#ifdef WIN32
|
||||
wchar_t dev_str[255];
|
||||
memset(dev_str, 0, sizeof(wchar_t) * 255);
|
||||
std::wstring env_name(L"PA_RECOMMENDED_OUTPUT_DEVICE");
|
||||
GetEnvironmentVariable(wtrim(env_name).c_str(), dev_str, 255);
|
||||
std::wistringstream env_result(dev_str);
|
||||
|
||||
default_driver = ao_default_driver_id();
|
||||
if (!env_result.eof()) {
|
||||
int env_dev = -1;
|
||||
env_result >> env_dev;
|
||||
|
||||
memset(&format, 0, sizeof(format));
|
||||
format.bits = 16;
|
||||
format.channels = 2;
|
||||
format.rate = AUDIO_FREQUENCY;
|
||||
format.byte_format = AO_FMT_LITTLE;
|
||||
if (env_result.eof()) { // read everything, was all a number
|
||||
if (env_dev >= 0) {
|
||||
std::cout << "Using preferred PortAudio device PA_RECOMMENDED_OUTPUT_DEVICE=" << env_dev << std::endl;
|
||||
preferred_device = env_dev;
|
||||
} else {
|
||||
std::cout << "Environment variable PA_RECOMMENDED_OUTPUT_DEVICE not set, using PortAudio defaults." << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "Environment variable PA_RECOMMENDED_OUTPUT_DEVICE didn't evaluate to a number, using PortAudio defaults." << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- Open driver -- */
|
||||
device = ao_open_live(default_driver, &format, NULL /* no options */);
|
||||
if (device == NULL) {
|
||||
fprintf(stderr, "Error opening device.\n");
|
||||
return (wxThread::ExitCode) 1;
|
||||
}
|
||||
outputParameters.device = (preferred_device != -1) ? preferred_device : Pa_GetDefaultOutputDevice();
|
||||
if (outputParameters.device == paNoDevice) {
|
||||
std::cout << "Error: No default output device.\n";
|
||||
}
|
||||
|
||||
while (!TestDestroy()) {
|
||||
outputParameters.channelCount = 2; /* Stereo output, most likely supported. */
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
if (m_pQueue->stackSize()) {
|
||||
stream = NULL;
|
||||
|
||||
while (m_pQueue->stackSize()) {
|
||||
AudioThreadTask task = m_pQueue->pop(); // pop a task from the queue. this will block the worker thread if queue is empty
|
||||
switch (task.m_cmd) {
|
||||
case AudioThreadTask::AUDIO_THREAD_DATA:
|
||||
err = Pa_OpenStream(&stream, NULL, &outputParameters, AUDIO_FREQUENCY, paFramesPerBufferUnspecified, paPrimeOutputBuffersUsingStreamCallback|paClipOff, &audioCallback, this);
|
||||
|
||||
int16_t buf[task.data->data.size()];
|
||||
err = Pa_StartStream(stream);
|
||||
if (err != paNoError) {
|
||||
std::cout << "Error starting stream: " << Pa_GetErrorText(err) << std::endl;
|
||||
std::cout << "\tPortAudio error: " << Pa_GetErrorText(err) << std::endl;
|
||||
}
|
||||
|
||||
for (int i = 0; i < task.data->data.size(); i++) {
|
||||
buf[i] = (int) (task.data->data[i] * 32760.0);
|
||||
}
|
||||
while (!TestDestroy()) {
|
||||
|
||||
ao_play(device, (char *) buf,
|
||||
task.data->data.size() * sizeof(int16_t));
|
||||
if (m_pQueue->stackSize()) {
|
||||
|
||||
delete task.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->Yield();
|
||||
this->Sleep(1);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl << "Audio Thread Done." << std::endl << std::endl;
|
||||
while (m_pQueue->stackSize()) {
|
||||
AudioThreadTask task = m_pQueue->pop(); // pop a task from the queue. this will block the worker thread if queue is empty
|
||||
switch (task.m_cmd) {
|
||||
case AudioThreadTask::AUDIO_THREAD_DATA:
|
||||
if (!TestDestroy()) {
|
||||
audio_queue.push(task.data->data);
|
||||
}
|
||||
delete task.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->Yield();
|
||||
this->Sleep(1);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl << "Audio Thread Done." << std::endl << std::endl;
|
||||
|
||||
return (wxThread::ExitCode) 0;
|
||||
return (wxThread::ExitCode) 0;
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,14 @@
|
||||
#include "wx/thread.h"
|
||||
|
||||
#include "AudioThreadQueue.h"
|
||||
#include "portaudio.h"
|
||||
#ifdef WIN32
|
||||
#include "pa_stream.h"
|
||||
#include "pa_debugprint.h"
|
||||
#endif
|
||||
|
||||
#include "ao/ao.h"
|
||||
static int audioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags, void *userData);
|
||||
|
||||
class AudioThread: public wxThread {
|
||||
public:
|
||||
@ -27,6 +33,6 @@ protected:
|
||||
AudioThreadQueue* m_pQueue;
|
||||
int m_ID;
|
||||
|
||||
ao_device *device;
|
||||
ao_sample_format format;
|
||||
PaStreamParameters outputParameters;
|
||||
PaStream *stream;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user