| 3335 | } |
| 3336 | |
| 3337 | void ModularSynth::SaveOutput() |
| 3338 | { |
| 3339 | ScopedMutex mutex(&mAudioThreadMutex, "SaveOutput()"); |
| 3340 | |
| 3341 | std::string save_prefix = "recording_"; |
| 3342 | if (!mCurrentSaveStatePath.empty()) |
| 3343 | { |
| 3344 | // This assumes that mCurrentSaveStatePath always has a valid filename at the end |
| 3345 | std::string filename = File(mCurrentSaveStatePath).getFileNameWithoutExtension().toStdString(); |
| 3346 | save_prefix = filename + "_"; |
| 3347 | } |
| 3348 | |
| 3349 | std::string filename = ofGetTimestampString(UserPrefs.recordings_path.Get() + save_prefix + "%Y-%m-%d_%H-%M.wav"); |
| 3350 | //string filenamePos = ofGetTimestampString("recordings/pos_%Y-%m-%d_%H-%M.wav"); |
| 3351 | |
| 3352 | assert(mRecordingLength <= mGlobalRecordBuffer->Size()); |
| 3353 | |
| 3354 | int channels = 2; |
| 3355 | auto wavFormat = std::make_unique<juce::WavAudioFormat>(); |
| 3356 | juce::File outputFile(ofToDataPath(filename)); |
| 3357 | outputFile.create(); |
| 3358 | auto outputTo = outputFile.createOutputStream(); |
| 3359 | assert(outputTo != nullptr); |
| 3360 | bool b1{ false }; |
| 3361 | auto writer = std::unique_ptr<juce::AudioFormatWriter>(wavFormat->createWriterFor(outputTo.release(), gSampleRate, channels, 16, b1, 0)); |
| 3362 | |
| 3363 | int samplesRemaining = mRecordingLength; |
| 3364 | const int chunkSize = 256; |
| 3365 | float leftChannel[chunkSize]; |
| 3366 | float rightChannel[chunkSize]; |
| 3367 | float* chunk[2]{ leftChannel, rightChannel }; |
| 3368 | while (samplesRemaining > 0) |
| 3369 | { |
| 3370 | int numSamples = MIN(chunkSize, samplesRemaining); |
| 3371 | for (int i = 0; i < numSamples; ++i) |
| 3372 | { |
| 3373 | chunk[0][i] = mGlobalRecordBuffer->GetSample(samplesRemaining - 1, 0); |
| 3374 | chunk[1][i] = mGlobalRecordBuffer->GetSample(samplesRemaining - 1, 1); |
| 3375 | --samplesRemaining; |
| 3376 | } |
| 3377 | writer->writeFromFloatArrays(chunk, channels, numSamples); |
| 3378 | } |
| 3379 | |
| 3380 | mGlobalRecordBuffer->ClearBuffer(); |
| 3381 | mRecordingLength = 0; |
| 3382 | |
| 3383 | TheTitleBar->DisplayTemporaryMessage("wrote " + filename); |
| 3384 | } |
| 3385 | |
| 3386 | const String& ModularSynth::GetTextFromClipboard() const |
| 3387 | { |
no test coverage detected