71 #if !defined(NSOUND_LIBPORTAUDIO) || !defined(NSOUND_CPP11)
75 M_THROW(
"Nsound was not compiled with portaudio.");
96 void my_atomic_init(std::atomic_uint & a,
unsigned int v)
100 std::atomic_init(&a, v);
113 sample_rate_(sample_rate),
118 unknown_error_count_(0),
119 stop_error_count_(0),
120 pa_underrun_count_(0),
121 pa_overrun_count_(0),
123 sine_(new Sine(sample_rate)),
125 pool_size_(n_buffers),
133 actual_latency_sec_(0)
145 PaError ecode = Pa_Initialize();
147 if(ecode != paNoError)
150 "Nsound::AudioPlaybackRt"
151 <<
": Pa_Initialize() failed"
153 << Pa_GetErrorText(ecode));
163 PaHostApiIndex api_index = -1;
167 api_index = Pa_HostApiTypeIdToHostApiIndex(paJACK);
171 api_index = Pa_GetDefaultHostApi();
181 "Nsound::AudioPlaybackRt"
182 <<
": could not find JACK host api! "
183 "Is the JACK server running?");
188 "Nsound::AudioPlaybackRt"
189 <<
": could not find host api to use!");
202 "Nsound::AudioPlaybackRt"
203 <<
": Pa_GetHostApiInfo() failed"
220 "Nsound::AudioPlaybackRt"
221 <<
": failed to get default output device!");
225 if(buffer_size_sec <= 0.0)
227 const PaDeviceInfo * dinfo = Pa_GetDeviceInfo(
235 "Nsound::AudioPlaybackRt"
236 <<
": Pa_GetDeviceInfo() failed\n");
239 buffer_size_sec = dinfo->defaultLowOutputLatency;
260 "Nsound::AudioPlaybackRt"
261 <<
": n_frames_per_buffer_ < 16"
265 for(
uint32 i = 0; i < n_buffers; ++i)
268 pool_.push_back(buf);
282 if(ecode != paNoError)
287 "Nsound::AudioPlaybackRt"
288 <<
": Pa_IsFormatSupported() failed ("
290 <<
" sample rate, paInt16, "
293 << Pa_GetErrorText(ecode));
299 ecode = Pa_OpenStream(
305 paClipOff | paDitherOff,
307 reinterpret_cast<void *>(
this));
309 if(ecode != paNoError)
314 "Nsound::AudioPlaybackRt:"
316 <<
": Pa_OpenStream() failed"
318 << Pa_GetErrorText(ecode));
329 "Nsound::AudioPlaybackRt"
330 <<
": Pa_GetStreamInfo() failed"
332 << Pa_GetErrorText(ecode));
343 PaError ecode = paNoError;
357 if(ecode != paNoError)
362 "Nsound::AudioPlaybackRt"
363 <<
": Pa_CloseStream() failed"
365 << Pa_GetErrorText(ecode));
368 ecode = Pa_Terminate();
370 if(ecode != paNoError)
373 "Nsound::AudioPlaybackRt"
374 <<
": Pa_Terminate() failed"
376 << Pa_GetErrorText(ecode));
385 unsigned long frame_count,
391 input, output, frame_count, time_info, status_flags);
394 #define SCALE static_cast<float64>(std::numeric_limits<int16>::max())
401 const uint32 frames_per_buffer,
407 int16 * dst_ptr =
reinterpret_cast<int16 *
>(output);
416 int16 * src = (*rd_ptr_)->data();
459 float64 sample = SCALE * rng.get(-0.666, 0.666);
460 dst_ptr[i] =
static_cast<int16>(sample);
480 dst_ptr[i++] = sample;
487 if(status_flags & paOutputUnderflow)
492 if(status_flags & paOutputOverflow)
510 if(ecode != paNoError)
515 "Nsound::AudioPlaybackRt"
516 <<
": Pa_StartStream() failed"
518 << Pa_GetErrorText(ecode));
530 if(ecode != paNoError)
534 "Nsound::AudioPlaybackRt"
535 <<
": Pa_StopStream() failed"
537 << Pa_GetErrorText(ecode));
545 for(
size_t i = 0; i <
pool_.size(); ++i)
548 std::fill(vec.begin(), vec.end(), 0);
562 play(
const AudioStream & as)
572 <<
"\nWARNING: AudioStream sample_rate != AudioPlaybackRt "
580 if(as.getNChannels() == 1)
588 for(
uint32 i = 0; i < as.getLength(); ++i)
590 play(as[0][i], as[1][i]);
597 play(
const Buffer & b)
611 return play(sample, sample);
636 std::this_thread::yield();
677 std::this_thread::yield();
698 const PaDeviceInfo * info =
nullptr;
704 M_THROW(
"Nsound::AudioPlaybackRt::getInfo():"
705 <<
": Pa_GetDeviceInfo() failed\n");
710 std::stringstream ss;
712 ss <<
"libportaudio Default Driver Info:" << endl
713 <<
" deviceCount: " << Pa_GetDeviceCount() << endl
714 <<
" structVersion: " << info->structVersion << endl
715 <<
" name: " << info->name << endl
716 <<
" hostApi(index): " << info->hostApi << endl
717 <<
" maxInputChannels: " << info->maxInputChannels << endl
718 <<
" maxOutputChannels: " << info->maxOutputChannels << endl
719 <<
" defaultLowInputLatency: " << info->defaultLowInputLatency << endl
720 <<
" defaultHighInputLatency: " << info->defaultHighInputLatency << endl
721 <<
" defaultLowOutputLatency: " << info->defaultLowOutputLatency << endl
722 <<
" defaultHighOutputLatency: " << info->defaultHighOutputLatency << endl
723 <<
" defaultSampleRate: " << info->defaultSampleRate << endl;
725 const PaHostApiInfo * api_info =
nullptr;
727 api_info = Pa_GetHostApiInfo(info->hostApi);
731 M_THROW(
"Nsound::AudioPlaybackRt::getInfo():"
732 <<
": Pa_GetHostApiInfo() failed\n");
736 ss <<
"libportaudio Default Host API Info:" << endl
737 <<
" structVersion: " << api_info->structVersion << endl
738 <<
" name: " << api_info->name << endl
739 <<
" deviceCount: " << api_info->deviceCount << endl
740 <<
" defaultInputDevice: " << api_info->defaultInputDevice << endl
741 <<
" defaultOutputDevice: " << api_info->defaultOutputDevice << endl;
750 std::stringstream ss;
753 <<
"AudioPlaybackRt:\n"
757 <<
" n_ready_ = " <<
n_ready_.load() <<
"\n"
765 <<
" driver_.n_frames_per_buffer_ = "
767 <<
" driver_.n_samples_per_buffer_ = "
773 <<
" driver_.out_params_->suggestedLatency = "
784 <<
" actual samplerate = " << sinfo->sampleRate <<
"\n"
785 <<
" actual output latency = " << sinfo->outputLatency <<
"\n";
789 <<
" PortAudio Device Driver Info:\n"
796 ss <<
" Pa_GetDeviceInfo() failed!\n";
801 <<
" Name: " << info->name <<
"\n"
802 <<
" maxOutputChannels: " << info->maxOutputChannels <<
"\n"
803 <<
" defaultSampleRate: " << info->defaultSampleRate <<
"\n"
804 <<
" defaultLowOutputLatency: " << info->defaultLowOutputLatency <<
"\n"
805 <<
" defaultHighOutputLatency: " << info->defaultHighOutputLatency <<
"\n";
816 AudioPlaybackRtDebug info;
823 info.pool_size =
static_cast<uint32>(
pool_.size());
833 for(
auto itor :
pool_)
835 if(itor == ptr_wr)
break;
842 for(
const auto & itor : pool_)
844 if(itor == ptr_rd)
break;
853 info.samplerate = sinfo->sampleRate;
857 info.samplerate = -1.0;
893 std::stringstream ss;
896 <<
"AudioPlaybackRtDebug:\n"
903 <<
" n_ready = " <<
n_ready <<
"\n"
904 <<
" wr_index = " <<
wr_index <<
"\n"
905 <<
" wr_ptr = " <<
wr_ptr <<
"\n"
906 <<
" rd_ptr = " <<
rd_ptr <<
"\n"
909 <<
" is_streaming = ";
914 ss <<
" n_history:\n";
918 ss <<
" " << n <<
"\n";
std::string debug_print()
uint32 n_samples_per_buffer_
#define M_ASSERT_VALUE(a, op, value)
BufferUnderrunMode underrun_mode_
void stop()
Stops playback.
Pool::iterator pool_begin_
std::string host_api_str_
uint32 unknown_error_count
std::string getInfo()
Returns information about the backend driver.
std::string __str__() const
float64 actual_latency_sec_
std::vector< uint32 > n_history
void operator>>(const AudioStream &lhs, AudioPlayback &rhs)
virtual float64 generate(const float64 &frequency)
This is a real-time method for the wavetable oscillator.
int _callback(const void *input, void *output, const uint32 frame_count, const PaStreamCallbackTimeInfo *time_info, PaStreamCallbackFlags status_flags)
AudioPlaybackRtDebug get_debug_info() const
void setBufferUnderrunMode(BufferUnderrunMode bum)
uint32 n_frames_per_buffer_
PaStreamParameters * out_params_
A Buffer for storing audio samples.
AudioPlaybackRt(float64 sample_rate=44100.0, uint32 channels=1, uint32 n_buffers=3, float64 buffer_size_sec=-1.0)
static int _pa_callback(const void *input, void *output, unsigned long frame_count, const PaStreamCallbackTimeInfo *time_info, PaStreamCallbackFlags status_flags, void *ap_obj)
std::vector< int16 > Int16Vector
uint32 samples_per_buffer
uint32 pa_underrun_count_
uint32 unknown_error_count_
std::vector< uint32 > n_history_
RandomNumberGenerator & getRandomNumberGenerator()
void play(const AudioStream &a)
Writes samples to the internal circular buffer to be played.