| 1 | /**************************************************************************** |
|---|
| 2 | |
|---|
| 3 | Copyright 2009 Virginia Polytechnic Institute and State University |
|---|
| 4 | |
|---|
| 5 | This file is part of the OSSIE AudioDevice. |
|---|
| 6 | |
|---|
| 7 | OSSIE AudioDevice is free software; you can redistribute it and/or modify |
|---|
| 8 | it under the terms of the GNU General Public License as published by |
|---|
| 9 | the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | (at your option) any later version. |
|---|
| 11 | |
|---|
| 12 | OSSIE AudioDevice is distributed in the hope that it will be useful, |
|---|
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
|---|
| 15 | Public License for more details. |
|---|
| 16 | |
|---|
| 17 | You should have received a copy of the GNU General Public License |
|---|
| 18 | along with OSSIE AudioDevice; if not, write to the Free Software |
|---|
| 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 20 | |
|---|
| 21 | ****************************************************************************/ |
|---|
| 22 | |
|---|
| 23 | #include <iostream> |
|---|
| 24 | #include "AudioDevice.h" |
|---|
| 25 | |
|---|
| 26 | #define AUDIODEVICE_PROPID_SAMPLERATERECORD "DCE:90b8fe0b-3b0b-4aee-bb2b-a9a989d22ba9" |
|---|
| 27 | #define AUDIODEVICE_PROPID_SAMPLERATEPLAYBACK "DCE:5a9b4f27-c604-4fe8-9661-4bf7a65e4ad4" |
|---|
| 28 | #define AUDIODEVICE_PROPID_BUFFERSIZERECORD "DCE:849f63b4-9b18-40cb-b318-956bedae94aa" |
|---|
| 29 | #define AUDIODEVICE_PROPID_BUFFERSIZEPLAYBACK "DCE:f3a3dd1f-b7e2-44a4-ad34-db0a6bea895f" |
|---|
| 30 | |
|---|
| 31 | #define AUDIODEVICE_NUMCHANNELS (2) |
|---|
| 32 | #define AUDIODEVICE_SAMPLEFORMAT (paFloat32) // paInt16 |
|---|
| 33 | |
|---|
| 34 | // Initializing constructor |
|---|
| 35 | AudioDevice_i::AudioDevice_i(char *uuid, char *label, char *profile, omni_condition *condition) |
|---|
| 36 | : Device_impl(uuid, label, profile), |
|---|
| 37 | component_running(condition), |
|---|
| 38 | isRunning(false) |
|---|
| 39 | { |
|---|
| 40 | DEBUG(3, AudioDevice, "constructor invoked") |
|---|
| 41 | |
|---|
| 42 | // set configured flags to false |
|---|
| 43 | // All properties must be configured before the stream is opened, |
|---|
| 44 | // after which any change in properties will be ignored |
|---|
| 45 | configured = false; |
|---|
| 46 | configured_prop_samplerate_record = false; |
|---|
| 47 | configured_prop_samplerate_playback = false; |
|---|
| 48 | configured_prop_buffersize_record = false; |
|---|
| 49 | configured_prop_buffersize_playback = false; |
|---|
| 50 | |
|---|
| 51 | buffer_playback = NULL; |
|---|
| 52 | buffer_record = NULL; |
|---|
| 53 | |
|---|
| 54 | // Create Port for output sound |
|---|
| 55 | dataOut = new standardInterfaces_i::complexShort_u("complexShortOut"); |
|---|
| 56 | dataIn = new standardInterfaces_i::complexShort_p("complexShortIn"); |
|---|
| 57 | // TODO: create port for input sound |
|---|
| 58 | |
|---|
| 59 | // initialize portaudio stream |
|---|
| 60 | PaError err = Pa_Initialize(); |
|---|
| 61 | if (err != paNoError) { |
|---|
| 62 | std::cerr << "ERROR: AudioDevice_i::AudioDevice_i(), could not initialize portaudio" << std::endl; |
|---|
| 63 | throw 0; |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | // Start the capture_sound thread |
|---|
| 67 | //capture_thread = new omni_thread(run_capture, (void *) this); |
|---|
| 68 | //capture_thread->start(); |
|---|
| 69 | |
|---|
| 70 | // Start playback_sound thread |
|---|
| 71 | //playback_thread = new omni_thread(run_playback, (void *) this); |
|---|
| 72 | //playback_thread->start(); |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | // Default destructor |
|---|
| 76 | AudioDevice_i::~AudioDevice_i() |
|---|
| 77 | { |
|---|
| 78 | if (buffer_playback) |
|---|
| 79 | delete [] buffer_playback; |
|---|
| 80 | if (buffer_record) |
|---|
| 81 | delete [] buffer_record; |
|---|
| 82 | |
|---|
| 83 | PaError err = Pa_Terminate(); |
|---|
| 84 | if (err != paNoError) { |
|---|
| 85 | std::cerr << "ERROR: AudioDevice_i::~AudioDevice_i(), could not terminate portaudio" << std::endl; |
|---|
| 86 | throw 0; |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | // static function for omni thread |
|---|
| 91 | void AudioDevice_i::run_capture( void * data ) |
|---|
| 92 | { |
|---|
| 93 | ((AudioDevice_i*) data)->capture_sound(); |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | // static function for omni thread |
|---|
| 98 | void AudioDevice_i::run_playback( void * data ) |
|---|
| 99 | { |
|---|
| 100 | ((AudioDevice_i*) data)->playback_sound(); |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | void AudioDevice_i::start() |
|---|
| 104 | throw (CF::Resource::StartError, CORBA::SystemException) |
|---|
| 105 | { |
|---|
| 106 | DEBUG(3, AudioDevice, "start() invoked") |
|---|
| 107 | |
|---|
| 108 | isRunning = true; |
|---|
| 109 | |
|---|
| 110 | // start the streams |
|---|
| 111 | StartStreams(); |
|---|
| 112 | } |
|---|
| 113 | |
|---|
| 114 | |
|---|
| 115 | void AudioDevice_i::stop() |
|---|
| 116 | throw (CF::Resource::StopError, CORBA::SystemException) |
|---|
| 117 | { |
|---|
| 118 | DEBUG(3, AudioDevice, "stop() invoked") |
|---|
| 119 | |
|---|
| 120 | isRunning = false; |
|---|
| 121 | |
|---|
| 122 | // stop the streams |
|---|
| 123 | StopStreams(); |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | CORBA::Object_ptr AudioDevice_i::getPort(const char* portName) |
|---|
| 127 | throw(CF::PortSupplier::UnknownPort, CORBA::SystemException) |
|---|
| 128 | |
|---|
| 129 | { |
|---|
| 130 | DEBUG(3, AudioDevice, "getPort() invoked with: " << portName) |
|---|
| 131 | |
|---|
| 132 | CORBA::Object_var u; |
|---|
| 133 | |
|---|
| 134 | u = dataOut->getPort(portName); |
|---|
| 135 | |
|---|
| 136 | if (!CORBA::is_nil(u)) |
|---|
| 137 | return u._retn(); |
|---|
| 138 | |
|---|
| 139 | // Port name not found; throw exception |
|---|
| 140 | throw CF::PortSupplier::UnknownPort(); |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | void AudioDevice_i::initialize() |
|---|
| 144 | throw (CF::LifeCycle::InitializeError, CORBA::SystemException) |
|---|
| 145 | { |
|---|
| 146 | DEBUG(3, AudioDevice, "initialize() invoked") |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | void AudioDevice_i::configure(const CF::Properties &props) |
|---|
| 150 | throw (CORBA::SystemException, |
|---|
| 151 | CF::PropertySet::InvalidConfiguration, |
|---|
| 152 | CF::PropertySet::PartialConfiguration) |
|---|
| 153 | { |
|---|
| 154 | DEBUG(3, AudioDevice, "configure() invoked. Number of props = " |
|---|
| 155 | << props.length() |
|---|
| 156 | ) |
|---|
| 157 | |
|---|
| 158 | if (configured) { |
|---|
| 159 | std::cout << "warning: AudioDevice_i::configure(), " |
|---|
| 160 | << "cannot reconfigure once all properties are set" |
|---|
| 161 | << std::endl; |
|---|
| 162 | return; |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | // read properties from .prf |
|---|
| 166 | |
|---|
| 167 | CORBA::Short n; |
|---|
| 168 | for (unsigned int i=0; i<props.length(); i++) |
|---|
| 169 | { |
|---|
| 170 | DEBUG(3, AudioDevice, "configure property id : " << props[i].id) |
|---|
| 171 | |
|---|
| 172 | if (strcmp(props[i].id, AUDIODEVICE_PROPID_SAMPLERATERECORD)==0) { |
|---|
| 173 | // sample rate: record |
|---|
| 174 | props[i].value >>= n; |
|---|
| 175 | samplerate_record = n; |
|---|
| 176 | configured_prop_samplerate_record = true; |
|---|
| 177 | DEBUG(3, AudioDevice, "sample rate (record): " << samplerate_record << " Hz") |
|---|
| 178 | |
|---|
| 179 | } else if (strcmp(props[i].id, AUDIODEVICE_PROPID_SAMPLERATEPLAYBACK)==0) { |
|---|
| 180 | // sample rate: playback |
|---|
| 181 | props[i].value >>= n; |
|---|
| 182 | samplerate_playback = n; |
|---|
| 183 | configured_prop_samplerate_playback = true; |
|---|
| 184 | DEBUG(3, AudioDevice, "sample rate (playback): " << samplerate_playback << " Hz") |
|---|
| 185 | |
|---|
| 186 | } else if (strcmp(props[i].id, AUDIODEVICE_PROPID_BUFFERSIZERECORD)==0) { |
|---|
| 187 | // buffer size: record |
|---|
| 188 | props[i].value >>= n; |
|---|
| 189 | buffersize_record = n; |
|---|
| 190 | configured_prop_samplerate_record = true; |
|---|
| 191 | DEBUG(3, AudioDevice, "buffer size (record): " << buffersize_record) |
|---|
| 192 | |
|---|
| 193 | } else if (strcmp(props[i].id, AUDIODEVICE_PROPID_BUFFERSIZEPLAYBACK)==0) { |
|---|
| 194 | // buffer size: playback |
|---|
| 195 | props[i].value >>= n; |
|---|
| 196 | buffersize_playback = n; |
|---|
| 197 | configured_prop_buffersize_playback = true; |
|---|
| 198 | DEBUG(3, AudioDevice, "buffer size (playback): " << buffersize_playback) |
|---|
| 199 | |
|---|
| 200 | } else { |
|---|
| 201 | std::cerr << "ERROR AudioDevice_i::configure(): unkown property id " |
|---|
| 202 | << props[i].id << std::endl; |
|---|
| 203 | throw(CF::PropertySet::InvalidConfiguration()); |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | // check configured flags |
|---|
| 207 | if ( configured_prop_samplerate_record && |
|---|
| 208 | configured_prop_samplerate_playback && |
|---|
| 209 | configured_prop_buffersize_record && |
|---|
| 210 | configured_prop_buffersize_playback) |
|---|
| 211 | { |
|---|
| 212 | configured = true; |
|---|
| 213 | DEBUG(3, AudioDevice, "configured") |
|---|
| 214 | } |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | // TODO: reconfigure streams |
|---|
| 218 | if (!configured) |
|---|
| 219 | return; |
|---|
| 220 | |
|---|
| 221 | // configure streams |
|---|
| 222 | ConfigureStreams(); |
|---|
| 223 | |
|---|
| 224 | // initialize buffers |
|---|
| 225 | buffer_playback = new float[2*buffersize_playback]; |
|---|
| 226 | buffer_record = new float[2*buffersize_record]; |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | void AudioDevice_i::releaseObject() |
|---|
| 230 | throw (CF::LifeCycle::ReleaseError, CORBA::SystemException) |
|---|
| 231 | { |
|---|
| 232 | DEBUG(3, AudioDevice, "releaseObject() invoked") |
|---|
| 233 | |
|---|
| 234 | component_running->signal(); |
|---|
| 235 | } |
|---|
| 236 | |
|---|
| 237 | void AudioDevice_i::OpenStreams() |
|---|
| 238 | throw (CF::Resource::StartError) |
|---|
| 239 | { |
|---|
| 240 | // ensure properties have been configured |
|---|
| 241 | if (!configured) { |
|---|
| 242 | std::cerr << "ERROR: AudioDevice_i::OpenStreams(), device not configured" << std::endl; |
|---|
| 243 | throw CF::Resource::StartError(); |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | PaError err; |
|---|
| 247 | |
|---|
| 248 | // open record stream |
|---|
| 249 | err = Pa_OpenStream( |
|---|
| 250 | &pa_stream_record, |
|---|
| 251 | NULL, // no input |
|---|
| 252 | &pa_params_record, |
|---|
| 253 | samplerate_record, |
|---|
| 254 | buffersize_record, |
|---|
| 255 | paClipOff, // disable clipping |
|---|
| 256 | portaudio_callback_record, |
|---|
| 257 | (void*)this); |
|---|
| 258 | |
|---|
| 259 | if (err != paNoError) { |
|---|
| 260 | std::cerr << "ERROR: AudioDevice_i::OpenStreams(), could not open portaudio stream: record" << std::endl; |
|---|
| 261 | throw CF::Resource::StartError(); |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | // open playback stream |
|---|
| 265 | err = Pa_OpenStream( |
|---|
| 266 | &pa_stream_playback, |
|---|
| 267 | &pa_params_playback, |
|---|
| 268 | NULL, // no output |
|---|
| 269 | samplerate_playback, |
|---|
| 270 | buffersize_playback, |
|---|
| 271 | paClipOff, // disable clipping |
|---|
| 272 | portaudio_callback_playback, |
|---|
| 273 | (void*)this); |
|---|
| 274 | |
|---|
| 275 | if (err != paNoError) { |
|---|
| 276 | std::cerr << "ERROR: AudioDevice_i::OpenStreams(), could not open portaudio stream: playback" << std::endl; |
|---|
| 277 | throw CF::Resource::StartError(); |
|---|
| 278 | } |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | void AudioDevice_i::StartStreams() |
|---|
| 282 | throw (CF::Resource::StartError) |
|---|
| 283 | { |
|---|
| 284 | if (!configured) { |
|---|
| 285 | std::cerr << "ERROR: AudioDevice_i::StartStreams(), device not configured" << std::endl; |
|---|
| 286 | throw CF::Resource::StartError(); |
|---|
| 287 | } |
|---|
| 288 | |
|---|
| 289 | // start record, playback threads |
|---|
| 290 | PaError err; |
|---|
| 291 | |
|---|
| 292 | |
|---|
| 293 | err = Pa_StartStream(pa_stream_record); |
|---|
| 294 | if (err != paNoError) { |
|---|
| 295 | std::cerr << "ERROR: AudioDevice_i::StartStreams(), could not start portaudio stream: record" << std::endl; |
|---|
| 296 | throw CF::Resource::StartError(); |
|---|
| 297 | } |
|---|
| 298 | |
|---|
| 299 | err = Pa_StartStream(pa_stream_playback); |
|---|
| 300 | if (err != paNoError) { |
|---|
| 301 | std::cerr << "ERROR: AudioDevice_i::StartStreams(), could not start portaudio stream: playback" << std::endl; |
|---|
| 302 | throw CF::Resource::StartError(); |
|---|
| 303 | } |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | void AudioDevice_i::StopStreams() |
|---|
| 307 | throw (CF::Resource::StopError) |
|---|
| 308 | { |
|---|
| 309 | PaError err; |
|---|
| 310 | |
|---|
| 311 | err = Pa_StopStream(pa_stream_record); |
|---|
| 312 | if (err != paNoError) { |
|---|
| 313 | std::cerr << "ERROR: AudioDevice_i::StopStreams(), could not stop portaudio stream: record" << std::endl; |
|---|
| 314 | throw CF::Resource::StopError(); |
|---|
| 315 | } |
|---|
| 316 | |
|---|
| 317 | err = Pa_StopStream(pa_stream_playback); |
|---|
| 318 | if (err != paNoError) { |
|---|
| 319 | std::cerr << "ERROR: AudioDevice_i::StopStreams(), could not stop portaudio stream: playback" << std::endl; |
|---|
| 320 | throw CF::Resource::StopError(); |
|---|
| 321 | } |
|---|
| 322 | |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | void AudioDevice_i::CloseStreams() |
|---|
| 326 | throw (CF::Resource::StopError) |
|---|
| 327 | { |
|---|
| 328 | PaError err; |
|---|
| 329 | |
|---|
| 330 | err = Pa_CloseStream(pa_stream_record); |
|---|
| 331 | if (err != paNoError) { |
|---|
| 332 | std::cerr << "ERROR: AudioDevice_i::CloseStreams(), could not close portaudio stream: record" << std::endl; |
|---|
| 333 | throw CF::Resource::StopError(); |
|---|
| 334 | } |
|---|
| 335 | |
|---|
| 336 | err = Pa_CloseStream(pa_stream_playback); |
|---|
| 337 | if (err != paNoError) { |
|---|
| 338 | std::cerr << "ERROR: AudioDevice_i::CloseStreams(), could not close portaudio stream: playback" << std::endl; |
|---|
| 339 | throw CF::Resource::StopError(); |
|---|
| 340 | } |
|---|
| 341 | } |
|---|
| 342 | |
|---|
| 343 | void AudioDevice_i::ConfigureStreams() |
|---|
| 344 | { |
|---|
| 345 | // configure parameters: record |
|---|
| 346 | pa_params_record.device = Pa_GetDefaultOutputDevice(); |
|---|
| 347 | pa_params_record.channelCount = AUDIODEVICE_NUMCHANNELS; |
|---|
| 348 | pa_params_record.sampleFormat = AUDIODEVICE_SAMPLEFORMAT; |
|---|
| 349 | pa_params_record.suggestedLatency = |
|---|
| 350 | Pa_GetDeviceInfo( pa_params_record.device )->defaultLowOutputLatency; |
|---|
| 351 | pa_params_record.hostApiSpecificStreamInfo = NULL; |
|---|
| 352 | |
|---|
| 353 | // configure parameters: playback |
|---|
| 354 | pa_params_playback.device = Pa_GetDefaultOutputDevice(); |
|---|
| 355 | pa_params_playback.channelCount = AUDIODEVICE_NUMCHANNELS; |
|---|
| 356 | pa_params_playback.sampleFormat = AUDIODEVICE_SAMPLEFORMAT; |
|---|
| 357 | pa_params_playback.suggestedLatency = |
|---|
| 358 | Pa_GetDeviceInfo( pa_params_playback.device )->defaultLowOutputLatency; |
|---|
| 359 | pa_params_playback.hostApiSpecificStreamInfo = NULL; |
|---|
| 360 | } |
|---|
| 361 | |
|---|
| 362 | void AudioDevice_i::capture_sound() |
|---|
| 363 | { |
|---|
| 364 | DEBUG(3, AudioDevice, "capture_sound() invoked") |
|---|
| 365 | PortTypes::ShortSequence L_out, R_out; |
|---|
| 366 | |
|---|
| 367 | L_out.length(1); |
|---|
| 368 | R_out.length(1); |
|---|
| 369 | |
|---|
| 370 | while(isRunning && configured) { |
|---|
| 371 | //dataOut->pushPacket(L_out, R_out); |
|---|
| 372 | } |
|---|
| 373 | } |
|---|
| 374 | |
|---|
| 375 | void AudioDevice_i::playback_sound() |
|---|
| 376 | { |
|---|
| 377 | DEBUG(3, AudioDevice, "playback_sound() invoked") |
|---|
| 378 | PortTypes::ShortSequence L_out, R_out; |
|---|
| 379 | |
|---|
| 380 | L_out.length(1); |
|---|
| 381 | R_out.length(1); |
|---|
| 382 | |
|---|
| 383 | while(isRunning && configured) { |
|---|
| 384 | //dataOut->pushPacket(L_out, R_out); |
|---|
| 385 | } |
|---|
| 386 | } |
|---|
| 387 | |
|---|
| 388 | void AudioDevice_i::SetRecordData(float * _data) |
|---|
| 389 | { |
|---|
| 390 | // copy data to buffer |
|---|
| 391 | for (unsigned int i=0; i<buffersize_record; i++) { |
|---|
| 392 | record_data_L[i] = buffer_record[2*i+0]; |
|---|
| 393 | record_data_R[i] = buffer_record[2*i+1]; |
|---|
| 394 | } |
|---|
| 395 | |
|---|
| 396 | // push data |
|---|
| 397 | dataOut->pushPacket(record_data_L, record_data_R); |
|---|
| 398 | } |
|---|
| 399 | |
|---|
| 400 | void AudioDevice_i::GetPlaybackData(float ** _data) |
|---|
| 401 | { |
|---|
| 402 | // wait for data |
|---|
| 403 | dataIn->getData(playback_data_L, playback_data_R); |
|---|
| 404 | |
|---|
| 405 | // copy to buffer |
|---|
| 406 | for (unsigned int i=0; i<buffersize_playback; i++) { |
|---|
| 407 | buffer_playback[2*i+0] = (*playback_data_L)[i]; |
|---|
| 408 | buffer_playback[2*i+1] = (*playback_data_R)[i]; |
|---|
| 409 | } |
|---|
| 410 | |
|---|
| 411 | // release input buffer |
|---|
| 412 | dataIn->bufferEmptied(); |
|---|
| 413 | |
|---|
| 414 | // return pointer to playback buffer |
|---|
| 415 | _data = &buffer_playback; |
|---|
| 416 | } |
|---|
| 417 | |
|---|
| 418 | int portaudio_callback_record( |
|---|
| 419 | const void *inputBuffer, |
|---|
| 420 | void *outputBuffer, |
|---|
| 421 | unsigned long framesPerBuffer, |
|---|
| 422 | const PaStreamCallbackTimeInfo* timeInfo, |
|---|
| 423 | PaStreamCallbackFlags statusFlags, |
|---|
| 424 | void *userData ) |
|---|
| 425 | { |
|---|
| 426 | //short int * in = (short int*)inputBuffer; |
|---|
| 427 | |
|---|
| 428 | // prevent unused variable warnings |
|---|
| 429 | (void) timeInfo; |
|---|
| 430 | (void) statusFlags; |
|---|
| 431 | (void) inputBuffer; |
|---|
| 432 | |
|---|
| 433 | unsigned long int i; |
|---|
| 434 | for (i=0; i<framesPerBuffer; i++) { |
|---|
| 435 | // write data to port |
|---|
| 436 | } |
|---|
| 437 | |
|---|
| 438 | return paContinue; |
|---|
| 439 | } |
|---|
| 440 | |
|---|
| 441 | int portaudio_callback_playback( |
|---|
| 442 | const void *inputBuffer, |
|---|
| 443 | void *outputBuffer, |
|---|
| 444 | unsigned long framesPerBuffer, |
|---|
| 445 | const PaStreamCallbackTimeInfo* timeInfo, |
|---|
| 446 | PaStreamCallbackFlags statusFlags, |
|---|
| 447 | void *userData ) |
|---|
| 448 | { |
|---|
| 449 | AudioDevice_i * device = (AudioDevice_i*)userData; |
|---|
| 450 | //short int * out = (short int*)outputBuffer; |
|---|
| 451 | // wait for data |
|---|
| 452 | float *data; |
|---|
| 453 | device->GetPlaybackData(&data); |
|---|
| 454 | |
|---|
| 455 | // prevent unused variable warnings |
|---|
| 456 | (void) timeInfo; |
|---|
| 457 | (void) statusFlags; |
|---|
| 458 | (void) inputBuffer; |
|---|
| 459 | |
|---|
| 460 | unsigned long int i; |
|---|
| 461 | for (i=0; i<framesPerBuffer; i++) { |
|---|
| 462 | // left |
|---|
| 463 | //*out++ = device->playback_data_L[i]; |
|---|
| 464 | |
|---|
| 465 | // right |
|---|
| 466 | //*out++ = device->playback_data_R[i]; |
|---|
| 467 | } |
|---|
| 468 | |
|---|
| 469 | return paContinue; |
|---|
| 470 | } |
|---|
| 471 | |
|---|
| 472 | |
|---|