| 278 | struct ex_offline_rendering : public labsound_example |
| 279 | { |
| 280 | virtual void play(int argc, char ** argv) override |
| 281 | { |
| 282 | AudioStreamConfig offlineConfig; |
| 283 | offlineConfig.device_index = 0; |
| 284 | offlineConfig.desired_samplerate = LABSOUND_DEFAULT_SAMPLERATE; |
| 285 | offlineConfig.desired_channels = LABSOUND_DEFAULT_CHANNELS; |
| 286 | |
| 287 | const float recording_time_ms = 1000.f; |
| 288 | |
| 289 | context = lab::MakeOfflineAudioContext(offlineConfig, recording_time_ms); |
| 290 | lab::AudioContext* ac = context.get(); |
| 291 | |
| 292 | std::shared_ptr<OscillatorNode> oscillator; |
| 293 | std::shared_ptr<AudioBus> musicClip = MakeBusFromSampleFile("samples/stereo-music-clip.wav", argc, argv); |
| 294 | std::shared_ptr<SampledAudioNode> musicClipNode; |
| 295 | std::shared_ptr<GainNode> gain; |
| 296 | |
| 297 | std::shared_ptr<RecorderNode> recorder(new RecorderNode(*ac, offlineConfig)); |
| 298 | |
| 299 | context->addAutomaticPullNode(recorder); |
| 300 | |
| 301 | recorder->startRecording(); |
| 302 | |
| 303 | { |
| 304 | ContextRenderLock r(context.get(), "ex_offline_rendering"); |
| 305 | |
| 306 | gain.reset(new GainNode(*ac)); |
| 307 | gain->gain()->setValue(0.125f); |
| 308 | |
| 309 | // osc -> gain -> recorder |
| 310 | oscillator.reset(new OscillatorNode(*ac)); |
| 311 | context->connect(gain, oscillator, 0, 0); |
| 312 | context->connect(recorder, gain, 0, 0); |
| 313 | oscillator->frequency()->setValue(880.f); |
| 314 | oscillator->setType(OscillatorType::SINE); |
| 315 | oscillator->start(0.0f); |
| 316 | |
| 317 | musicClipNode.reset(new SampledAudioNode(*ac)); |
| 318 | context->connect(recorder, musicClipNode, 0, 0); |
| 319 | musicClipNode->setBus(r, musicClip); |
| 320 | musicClipNode->schedule(0.0); |
| 321 | } |
| 322 | |
| 323 | bool complete = false; |
| 324 | context->offlineRenderCompleteCallback = [ac, &recorder, &complete]() { |
| 325 | recorder->stopRecording(); |
| 326 | |
| 327 | printf("Recorded %f seconds of audio\n", recorder->recordedLengthInSeconds()); |
| 328 | |
| 329 | ac->removeAutomaticPullNode(recorder); |
| 330 | recorder->writeRecordingToWav("ex_offline_rendering.wav", false); |
| 331 | complete = true; |
| 332 | }; |
| 333 | |
| 334 | // Offline rendering happens in a separate thread and blocks until complete. |
| 335 | // It needs to acquire the graph + render locks, so it must |
| 336 | // be outside the scope of where we make changes to the graph. |
| 337 | context->startOfflineRendering(); |
nothing calls this directly
no test coverage detected