AudioFileSelector::AudioFileSelector() { AudioFormatManager formatManager; formatManager.registerBasicFormats(); playButton = new TextButton ("u", "click here to play the current audio file"); playButton->addListener (this); playButton->setColour (TextButton::buttonColourId, Colours::white); playButton->setColour (TextButton::buttonOnColourId, Colours::grey); playButton->setConnectedEdges (Button::ConnectedOnRight | Button::ConnectedOnLeft); fileChooser = new FilenameComponent ("AudioFile", File::nonexistent, true, false, false, formatManager.getWildcardForAllFormats(), String::empty, "(choose an audio file)"); addAndMakeVisible (playButton); addAndMakeVisible (fileChooser); fileChooser->addListener (this); fileChooser->setBrowseButtonText ("..."); }
void TrackComponent::filesDropped(const StringArray & files, int x, int) { for (auto current = files.begin(), end = files.end(); current != end; ++current) { const String fileString = *current; String format; if(fileString.contains(".wav") || fileString.contains(".WAV")) format = "WAV"; else if(fileString.contains(".aif") || fileString.contains(".aiff") || fileString.contains(".AIF") || fileString.contains(".AIFF")) format = "AIFF"; else if(fileString.contains(".flac") || fileString.contains(".FLAC")) format = "FLAC"; File file(fileString); AudioFormatManager formatManager; formatManager.registerBasicFormats(); AudioFormatReader* reader = formatManager.createReaderFor(file); Region* region = new SampleRegion(reader, 1, &file); if(x > _mixerOffset) { int64 samplesRange = secondsToSamples((double)_numberOfClips, _sampleRate); int64 positionSamples = pixelsToSamples(x - _mixerOffset, _numberOfClips * _pixelsPerClip, samplesRange); _track->add(positionSamples, region); createRegionGUI(x, region, formatManager, file); } else if(x < _mixerOffset) { _track->add(0, region); createRegionGUI(_mixerOffset, region, formatManager, file); } } }
void IRAgent::setFile(const File& file, size_t fileChannel) { AudioFormatManager formatManager; formatManager.registerBasicFormats(); ScopedPointer<AudioFormatReader> audioFormatReader(formatManager.createReaderFor(file)); { ScopedLock lock(_mutex); if (audioFormatReader) { if (_file == file && _fileChannel == fileChannel) { return; } _file = file; _fileSampleCount = static_cast<size_t>(audioFormatReader->lengthInSamples); _fileChannelCount = static_cast<size_t>(audioFormatReader->numChannels); _fileSampleRate = audioFormatReader->sampleRate; _fileChannel = fileChannel; } else { _file = File::nonexistent; _fileSampleCount = 0; _fileChannelCount = 0; _fileSampleRate = 0.0; _fileChannel = 0; } } propagateChange(); updateConvolver(); }
void setTickSample (void const* audioData, int dataBytes) { ScopedPointer <MemoryInputStream> mis (new MemoryInputStream (audioData, dataBytes, false)); m_synth.clearVoices (); m_synth.clearSounds (); AudioFormatManager afm; afm.registerBasicFormats (); { ScopedPointer <AudioFormatReader> afr (afm.createReaderFor (mis)); if (afr != nullptr) { mis.release (); BigInteger midiNotes; midiNotes.setRange (0, 127, true); SynthesiserSound::Ptr sound = new SamplerSound ( "Tick", *afr, midiNotes, 60, 0, 0, 60./40.); m_synth.addSound (sound); m_synth.addVoice (new SamplerVoice); } } }
AudioFormatReader* AudioFilePlayer::audioFormatReaderFromFile(const File& audioFile) { AudioFormatManager formatManager; formatManager.registerBasicFormats(); currentFile = audioFile; return formatManager.createReaderFor (audioFile); }
void AudioFilePlayer::setPolyphony (int value) { int arraySize = fileSource.size(); if (value > arraySize) { AudioFormatManager formatManager; formatManager.registerBasicFormats(); ScopedPointer <AudioFormatReader> reader (formatManager.createReaderFor (currentFile)); for (int i = 0; i < (value - arraySize); i++) { //add element fileSource.add (new AudioTransportSource()); //add new element as an input source to audioMixer audioMixer.addInputSource(fileSource.getLast(), false); //apply audio file to new element if (currentFile != File::nonexistent) { //here, do I need to do the... //if (reader != 0) //{ /// currentAudioFileSource = new AudioFormatReaderSource (reader, true); //} //... like in setAudioFile() above? //this will involve having to delete currentAudioFileSource first. addtoFileSourceArray (fileSource.size()-1, reader); } } //set AFTER elements have been created so any calls to //isCurrentlyPlaying() don't cause a crash due to //elements not existing yet. polyphony = value; } else if (value < arraySize) { //set BEFORE elements have been deleted so any calls to //isCurrentlyPlaying() don't cause a crash due to //elements not existing anymore. polyphony = value; for (int i = 0; i < (arraySize - value); i++) { //remove elements audioMixer.removeInputSource(fileSource.getLast()); fileSource.removeLast(); } } }
const char* carla_get_supported_file_extensions() { carla_debug("carla_get_supported_file_extensions()"); static CarlaString retText; if (retText.isEmpty()) { retText = // Base types "*.carxp;*.carxs" // MIDI files ";*.mid;*.midi" #ifdef HAVE_FLUIDSYNTH // fluidsynth (sf2) ";*.sf2" #endif #ifdef HAVE_LINUXSAMPLER // linuxsampler (gig and sfz) ";*.gig;*.sfz" #endif #ifdef WANT_ZYNADDSUBFX // zynaddsubfx presets ";*.xmz;*.xiz" #endif ; #ifndef BUILD_BRIDGE // Audio files { using namespace juce; AudioFormatManager afm; afm.registerBasicFormats(); String juceFormats; for (AudioFormat **it=afm.begin(), **end=afm.end(); it != end; ++it) { const StringArray& exts((*it)->getFileExtensions()); for (String *eit=exts.begin(), *eend=exts.end(); eit != eend; ++eit) juceFormats += String(";*" + (*eit)).toRawUTF8(); } retText += juceFormats.toRawUTF8(); } #endif } return retText; }
//- LISP API - // playback-set-file (string)fileName -> t/nil base::cell_t set_file(base::lisp &gl, base::cell_t c, base::cells_t &) { if (base::lisp::validate(c, base::cell::list(1), base::cell::typeString)) { const auto &fname = c + 1; // stop current playback ts.stop(); ts.setSource(nullptr); frs = nullptr; AudioFormatReader *r; // ectract CUE information (if any) std::regex cue("^(.*):(\\d+):(\\d+)$"); std::smatch result; std::regex_search(fname->s, result, cue); if (result.size() == 4) { // is cue int32 start = base::fromStr<int32>(result[2].str()); int32 end = base::fromStr<int32>(result[3].str()); int32 duration = end - start; AudioFormatReader *tr = fm.createReaderFor(File(result[1].str())); // start, end are in frames (1 frame = 1/75 second) - convert to sample float samplesInOneSecond = tr->sampleRate; // AudioSubsectionReader will handle channels count float startSecond = (float)start / 75.0f; float durationSecond = (float)duration / 75.0f; float startSample = startSecond * samplesInOneSecond; float durationSamples = durationSecond * samplesInOneSecond; // some CUE may have 0 length (play to end) if (end <= start) durationSamples = tr->lengthInSamples; r = new AudioSubsectionReader(tr, (int)startSample, (int)durationSamples, true); } else { // regular file r = fm.createReaderFor(File(fname->s)); } if (r) { frs = new AudioFormatReaderSource(r, true); ts.setSource(frs, 32768, &thread, r->sampleRate); return gl.t(); } gl.signalError(base::strs("file not found or file format not supported: ", fname->s)); return gl.nil(); } gl.signalError("playback-set-file: invalid arguments, expected (string)"); return gl.nil(); }
void init(base::lisp &gl) { fm.registerBasicFormats(); thread.startThread(3); dm.addAudioCallback(&asp); asp.setSource(&ts); pl = new playbackListener(gl); ts.addChangeListener(pl); }
Oscillator::Oscillator (double sampleRate) : sampRate(sampleRate), squareBuffer(1, 22071), sawBuffer(1, 21984), sawDownBuffer(1, 21984) { currentPhase = 0.0; currentSample = 0.0; stepSize = 0; squareBuffer.clear(); sawBuffer.clear(); sawDownBuffer.clear(); sharedMemory.enter(); AudioFormatManager formatManager; formatManager.registerBasicFormats(); ScopedPointer <AudioFormatReader> squareReader (formatManager.createReaderFor(new MemoryInputStream (MainBinaryData::squarewave20500_wav, MainBinaryData::squarewave20500_wavSize, false))); squareReader->read(&squareBuffer, 0, squareReader->lengthInSamples, 0, true, false); squareNumSamples = squareReader->lengthInSamples; ScopedPointer <AudioFormatReader> sawReader (formatManager.createReaderFor(new MemoryInputStream (MainBinaryData::sawwave20500_wav, MainBinaryData::sawwave20500_wavSize, false))); sawReader->read(&sawBuffer, 0, sawReader->lengthInSamples, 0, true, false); ScopedPointer <AudioFormatReader> sawDownReader (formatManager.createReaderFor(new MemoryInputStream (MainBinaryData::sawdownwave20500_wav, MainBinaryData::sawdownwave20500_wavSize, false))); sawDownReader->read(&sawDownBuffer, 0, sawDownReader->lengthInSamples, 0, true, false); sawNumSamples = sawReader->lengthInSamples; sharedMemory.exit(); }
bool FileWatcherThread::readDataFile(AudioSampleBuffer *buffer, File file) { AudioFormatManager formatManager; formatManager.registerBasicFormats(); ScopedPointer<AudioFormatReader> reader = formatManager.createReaderFor(file); if (reader != 0) { int sampleCount = (int) reader->lengthInSamples; buffer->setSize(kNumSampleChannels, sampleCount, false, true, false); reader->read(buffer, 0, sampleCount, 0, true, true); if (reader->numChannels != kNumSampleChannels) { printf("File is mono, copying data to second channel\n"); buffer->copyFrom(1, 0, *buffer, 0, 0, sampleCount); } return true; } return false; }
KeyAnalysisThread::KeyAnalysisThread(SingleAudioFileForAnalysis* _fileToAnalyze, AudioFormatManager& _audioFormatManager) : Thread("Key Analysis Thread" + _fileToAnalyze->getFileName()), fileToAnalyze(_fileToAnalyze) //audioFormatManager(_audioFormatManager) { audioFormatReader = _audioFormatManager.createReaderFor(_fileToAnalyze->getFileToBeAnalyzed()); DBG("Creating thread: " << getThreadName()); interval = Random::getSystemRandom().nextInt(50) + 8; startThread(); }
//called from either the constructor, or setSamplerAudioFilePath() in PadSettings void AudioFilePlayer::setAudioFile (File audioFile_) { if (audioFile_ != File::nonexistent) { //passes in pads audio file File audioFile (audioFile_); //if the audio file is different from the previous one, stop and load in the new file if (audioFile != currentFile) { // unload the previous file source and delete it.. broadcaster.sendActionMessage("OFF"); for (int i = 0; i < polyphony; i++) { fileSource[i]->stop(); fileSource[i]->setPosition(0.0); fileSource[i]->setSource (0); } deleteAndZero (currentAudioFileSource); // create a new file source from the file.. // get a format manager and set it up with the basic types (wav, ogg and aiff). AudioFormatManager formatManager; formatManager.registerBasicFormats(); AudioFormatReader* reader = formatManager.createReaderFor (audioFile); if (reader != 0) { currentFile = audioFile; currentAudioFileSource = new AudioFormatReaderSource (reader, true); //add the audio file to the fileSource array for (int i = 0; i < polyphony; i++) { addtoFileSourceArray(i, reader); } } } } }
void DiskIn::initWithJuceFile(File const& file, bool loopFlag, const double startTime, const int numFrames, const UGen::DoneAction doneAction) throw() { AudioFormatManager formatManager; formatManager.registerBasicFormats(); AudioFormatReader* reader = formatManager.createReaderFor (file); int numChannels = reader->numChannels; delete reader; initInternal(numChannels); generateFromProxyOwner(new DiskInUGenInternal(file, numChannels, loopFlag, startTime, numFrames, doneAction)); }
//- LISP API - // playback-set-file (string)fileName -> t/nil base::cell_t set_file(base::lisp &gl, base::cell_t c, base::cells_t &) { if (base::lisp::validate(c, base::cell::list(1), base::cell::typeString)) { const auto &fname = c + 1; // stop current playback ts.stop(); ts.setSource(nullptr); frs = nullptr; AudioFormatReader *r; // ectract CUE information (if any) std::regex cue("^(.*):(\\d+):(\\d+)$"); std::smatch result; std::regex_search(fname->s, result, cue); if (result.size() == 4) { // is cue int32 start = base::fromStr<int32>(result[2].str()); int32 end = base::fromStr<int32>(result[3].str()); AudioFormatReader *tr = fm.createReaderFor(File(result[1].str())); r = new AudioSubsectionReader(tr, start, end - start, true); } else { // regular file r = fm.createReaderFor(File(fname->s)); } if (r) { frs = new AudioFormatReaderSource(r, true); ts.setSource(frs, 32768, &thread, r->sampleRate); return gl.t(); } gl.signalError(base::strs("file not found or file format not supported: ", fname->s)); return gl.nil(); } gl.signalError("playback-set-file: invalid arguments, expected (string)"); return gl.nil(); }
void AudioDemoPlaybackPage::loadFileIntoTransport (const File& audioFile) { // unload the previous file source and delete it.. transportSource.stop(); transportSource.setSource (0); deleteAndZero (currentAudioFileSource); // get a format manager and set it up with the basic types (wav and aiff). AudioFormatManager formatManager; formatManager.registerBasicFormats(); AudioFormatReader* reader = formatManager.createReaderFor (audioFile); if (reader != 0) { currentAudioFileSource = new AudioFormatReaderSource (reader, true); // ..and plug it into our transport source transportSource.setSource (currentAudioFileSource, 32768, // tells it to buffer this many samples ahead reader->sampleRate); } }
void loadFileIntoTransport (const File& audioFile) { // unload the previous file source and delete it.. transportSource.stop(); transportSource.setSource (nullptr); currentAudioFileSource = nullptr; AudioFormatReader* reader = formatManager.createReaderFor (audioFile); if (reader != nullptr) { currentAudioFileSource = new AudioFormatReaderSource (reader, true); // ..and plug it into our transport source transportSource.setSource (currentAudioFileSource, 32768, // tells it to buffer this many samples ahead &thread, // this is the background thread to use for reading-ahead reader->sampleRate); // allows for sample rate correction } }
void Dictionary::createDictionary(std::string outputDir) { //open output file std::fstream outputFile; outputFile.open(outputDir+"W.txt", std::ios::out); if (!outputFile.is_open()) { std::cout << "Text file open error!"; return; } //prepare to read file AudioFormatManager formatManager; formatManager.registerBasicFormats(); kiss_fft_cfg fwd= kiss_fft_alloc(FFT_SIZE,0,NULL,NULL); // HARD CODING HERE. REQUIRES MODIFICATION float fs = 44100; int nChannels = 2; numSamplesToRead = round(fs*SECS_PER_BLOCK); numSamplesPerBlock = numSamplesToRead/DOWNSAMPLE_RATE; AudioSampleBuffer buffer(nChannels, numSamplesToRead); float* audioBuffer = new float[numSamplesToRead]; for (int track = 21; track<=108; track++) { // ANY BETTER WAYS TO DEAL WITH FILENAMES?? std::string strFileDir = sampleFileFolder + "MAPS_ISOL_NO_M_S0_M"+std::to_string(track)+"_AkPnBcht.wav"; File audioFileS0(strFileDir); AudioFormatReader* reader; if (audioFileS0.exists()) { reader = formatManager.createReaderFor(audioFileS0); } else { strFileDir = sampleFileFolder + "MAPS_ISOL_NO_M_S1_M"+std::to_string(track)+"_AkPnBcht.wav"; File audioFileS1(strFileDir); reader = formatManager.createReaderFor(audioFileS1); } reader->read(&buffer, 0, numSamplesToRead, fs, true, true); float* leftBuffer = buffer.getSampleData(0); float* rightBuffer = buffer.getSampleData(1); for (int i=0; i<numSamplesToRead; i++) { audioBuffer[i] = (leftBuffer[i]+rightBuffer[i])/2; } antiAlias(audioBuffer, numSamplesToRead); for (int i=0; i<numSamplesPerBlock; i++) { audio[i].real( audioBuffer[i*DOWNSAMPLE_RATE]*hammWin(i, numSamplesPerBlock) ); audio[i].imag(0); } for (int i = numSamplesPerBlock; i<FFT_SIZE; i++) { audio[i].real(0); audio[i].imag(0); } kiss_fft(fwd, (kiss_fft_cpx*) audio, (kiss_fft_cpx*)spectrum); for (int i = 0; i<FFT_SIZE/2; i++) { W[i][track-21] = abs(spectrum[i]); //HARD CODING HERE! } delete reader; } delete [] audioBuffer; for(int i = 0; i< FFT_SIZE/2; i++){ for (int j = 0; j<N_NOTES; j++) { // fwrite(&W[i][j], sizeof(float), 1, file); outputFile << W[i][j] << "\t"; } outputFile<<std::endl; } outputFile.close(); }
static AudioFormatManager& getAudioFormatManagerInstance() { static AudioFormatManager afm; afm.registerBasicFormats(); return afm; }
void TrackComponent::mouseDown(const MouseEvent &e) { ModifierKeys modifiers = ModifierKeys::getCurrentModifiersRealtime(); int posX; // check the mod keys .. if (modifiers.isPopupMenu() || modifiers.isCtrlDown()) { ScopedPointer<PopupMenu> trackMenu_ = new PopupMenu(); trackMenu_->clear(); trackMenu_->addCommandItem(&_commands, MainWindow::showMixer); trackMenu_->addItem(1, "Add Region", true); MouseEvent ev = e.getEventRelativeTo(this); for(auto region : _regionComponents) { posX = ev.x; region->setBroughtToFrontOnMouseClick(true); if(region->getPositionX() < posX && posX < (region->getPositionX() + region->getRegionWidth())) { trackMenu_->addItem(2, "Remove Region", true); } } switch (trackMenu_->show()) { case 1: { FileChooser chooser("Select an audio file to add...", File::nonexistent, "*.wav; *aif; *.flac"); if (chooser.browseForFileToOpen()) { File audioFile(chooser.getResult()); const String fileString = audioFile.getFullPathName(); String format; if (fileString.contains(".wav")) format = "WAV"; else if (fileString.contains(".aif") || fileString.contains(".aiff")) format = "AIFF"; else if (fileString.contains(".flac")) format = "FLAC"; AudioFormatManager formatManager; formatManager.registerBasicFormats(); AudioFormatReader* reader = formatManager.createReaderFor(audioFile); Audio::Region* region = new Audio::SampleRegion(reader, 1, &audioFile); Point<int> position = e.getPosition(); int x = position.getX(); if (x > _mixerOffset) { int64 samplesRange = secondsToSamples(100, _sampleRate); int64 positionSamples = pixelsToSamples(x - _mixerOffset, 100 * _pixelsPerClip, samplesRange); _track->add(positionSamples, region); createRegionGUI(x, region, formatManager, audioFile); getParentComponent()->resized(); } else if (x < _mixerOffset) { _track->add(0, region); createRegionGUI(_mixerOffset, region, formatManager, audioFile); getParentComponent()->resized(); } } } break; case 2: { CriticalSection critical; critical.enter(); for(size_t i = 0; i < _regionComponents.size(); ++i) { Rectangle<int> bounds_ = _regionComponents.at(i)->getBounds(); posX = ev.x; if((int)_regionComponents.at(i)->getPositionX() < posX && posX < ((int)_regionComponents.at(i)->getPositionX() + (int)_regionComponents.at(i)->getRegionWidth())) { _track->remove(_regionComponents.at(i)->getRegion(), _posX.at(i)); std::vector<RegionComponent*>::iterator regit = _regionComponents.begin() + i; RegionComponent* component = _regionComponents.at(i); removeChildComponent(_regionComponents.at(i)); _regionComponents.erase(regit); delete component; _regions.erase(_posX.at(i)); std::vector<int64>::iterator posit = _posX.begin() + i;; _posX.erase(posit); std::vector<int64>::iterator sampsit = _sizeSamps.begin() + i;; _sizeSamps.erase(sampsit); } } critical.exit(); } default: break; } } }
AudioFilePlayer::AudioFilePlayer(int samplerPadNumber, ModeSampler &ref, TimeSliceThread* audioTransportSourceThread_) : padNumber(samplerPadNumber), modeSamplerRef(ref) { audioTransportSourceThread = audioTransportSourceThread_; currentAudioFileSource = NULL; AudioFormatManager formatManager; formatManager.registerBasicFormats(); //init all effects to be null gainAndPan = nullptr; lowPassFilter = nullptr; highPassFilter = nullptr; bandPassFilter = nullptr; reverb = nullptr; delay = nullptr; flanger = nullptr; tremolo = nullptr; distortion = nullptr; bitcrusher = nullptr; //set a default sample rate value here as if we load up a Sampler Pad wth reverb already applied //to it the application will crash otherwise, as the reverb object sample rate will attempt to be set before //prepareToPlay() is called that sets the correct sample rate. sampleRate_ = 44100; //grab the setting values (so that if this object is deleted and recreated, it will hold the previous settings) //do i need to enter shared memory here? gain = PAD_SETTINGS->getSamplerGain(); //should this be cubed? panLeft = PanControl::leftChanPan_(PAD_SETTINGS->getSamplerPan()); panRight = PanControl::rightChanPan_(PAD_SETTINGS->getSamplerPan()); triggerMode = PAD_SETTINGS->getSamplerTriggerMode(); shouldLoop = PAD_SETTINGS->getSamplerShouldLoop(); indestructible = PAD_SETTINGS->getSamplerIndestructible(); shouldFinishLoop = PAD_SETTINGS->getSamplerShouldFinishLoop(); sticky = PAD_SETTINGS->getSamplerSticky(); currentPlayingState = currentPressureValue = 0; //set effect to default 0, and then call set effect to create the effect object //This alg. prevents any crashes caused within prepareToPlay when trying to //set the sampleRate, where the effect object must exist effect = 0; setEffect(PAD_SETTINGS->getSamplerEffect()); quantizeMode = PAD_SETTINGS->getQuantizeMode(); attackTime = PAD_SETTINGS->getSamplerAttackTime(); releaseTime = PAD_SETTINGS->getSamplerReleaseTime(); triggerModeData.playingStatus = 0; prevPadValue = pressureValue = 0; playingLastLoop = false; attackSamples = attackTime * sampleRate_; releaseSamples = releaseTime * sampleRate_; isInAttack = isInRelease = isInStartRamp = false; attackPosition = releasePosition = startRampPosition = 0; attRelGainL = attRelGainR = prevGainL = prevGainR = 0; velocityGain = 1.0; velocity = 127; currentFile = File::nonexistent; setPolyphony(PAD_SETTINGS->getSamplerPolyphony()); setAudioFile(PAD_SETTINGS->getSamplerAudioFilePath()); columnNumber = sequenceNumber = 0; nextFileSourceIndex = 0; hasAlertedGui = false; broadcaster.addActionListener(this); }
bool Mcfx_convolverAudioProcessor::loadIr(AudioSampleBuffer* IRBuffer, const File& audioFile, int channel, double &samplerate, float gain, int offset, int length) { if (!audioFile.existsAsFile()) { std::cout << "ERROR: file does not exist!!" << std::endl; return false; } AudioFormatManager formatManager; // this can read .wav and .aiff formatManager.registerBasicFormats(); AudioFormatReader* reader = formatManager.createReaderFor(audioFile); if (!reader) { std::cout << "ERROR: could not read impulse response file!" << std::endl; return false; } //AudioFormatReader* reader = wavFormat.createMemoryMappedReader(audioFile); int64 ir_length = (int)reader->lengthInSamples-offset; if (ir_length <= 0) { std::cout << "wav file has zero samples" << std::endl; return false; } if (reader->numChannels <= channel) { std::cout << "wav file doesn't have enough channels: " << reader->numChannels << std::endl; return false; } AudioSampleBuffer ReadBuffer(reader->numChannels, ir_length); // create buffer reader->read(&ReadBuffer, 0, ir_length, offset, true, true); // set the samplerate -> maybe we have to resample later... samplerate = reader->sampleRate; //std::cout << "ReadRMS: " << ReadBuffer.getRMSLevel(channel, 0, ir_length) << std::endl; // check if we want a shorter impulse response if (ir_length > length && length != 0) ir_length = length; // copy the wanted channel into our IR Buffer IRBuffer->setSize(1, ir_length); IRBuffer->copyFrom(0, 0, ReadBuffer, channel, 0, ir_length); // scale ir with gain IRBuffer->applyGain(gain); // std::cout << "ReadRMS: " << IRBuffer->getRMSLevel(0, 0, ir_length) << std::endl; delete reader; return true; }
namespace playback { AudioDeviceManager dm; AudioFormatManager fm; AudioSourcePlayer asp; AudioTransportSource ts; ScopedPointer<AudioFormatReaderSource> frs; TimeSliceThread thread("audio playback"); class playbackListener : public ChangeListener { base::lisp ≷ public: base::string functionId; bool enabled; playbackListener(base::lisp &gli) : gl(gli), enabled(false) {} void changeListenerCallback(ChangeBroadcaster *source) override { if (source == &ts && enabled) { gl.eval(base::strs("(", functionId, ")")); } } }; playbackListener *pl = nullptr; void init(base::lisp &gl) { fm.registerBasicFormats(); thread.startThread(3); dm.addAudioCallback(&asp); asp.setSource(&ts); pl = new playbackListener(gl); ts.addChangeListener(pl); } void shutdown() { ts.removeAllChangeListeners(); ts.setSource(nullptr); asp.setSource(nullptr); dm.removeAudioCallback(&asp); delete pl; pl = nullptr; } //- LISP API - // playback-set-file (string)fileName -> t/nil base::cell_t set_file(base::lisp &gl, base::cell_t c, base::cells_t &) { if (base::lisp::validate(c, base::cell::list(1), base::cell::typeString)) { const auto &fname = c + 1; // stop current playback ts.stop(); ts.setSource(nullptr); frs = nullptr; AudioFormatReader *r; // ectract CUE information (if any) std::regex cue("^(.*):(\\d+):(\\d+)$"); std::smatch result; std::regex_search(fname->s, result, cue); if (result.size() == 4) { // is cue int32 start = base::fromStr<int32>(result[2].str()); int32 end = base::fromStr<int32>(result[3].str()); int32 duration = end - start; AudioFormatReader *tr = fm.createReaderFor(File(result[1].str())); // start, end are in frames (1 frame = 1/75 second) - convert to sample float samplesInOneSecond = tr->sampleRate; // AudioSubsectionReader will handle channels count float startSecond = (float)start / 75.0f; float durationSecond = (float)duration / 75.0f; float startSample = startSecond * samplesInOneSecond; float durationSamples = durationSecond * samplesInOneSecond; // some CUE may have 0 length (play to end) if (end <= start) durationSamples = tr->lengthInSamples; r = new AudioSubsectionReader(tr, (int)startSample, (int)durationSamples, true); } else { // regular file r = fm.createReaderFor(File(fname->s)); } if (r) { frs = new AudioFormatReaderSource(r, true); ts.setSource(frs, 32768, &thread, r->sampleRate); return gl.t(); } gl.signalError(base::strs("file not found or file format not supported: ", fname->s)); return gl.nil(); } gl.signalError("playback-set-file: invalid arguments, expected (string)"); return gl.nil(); } // playback-unload-file base::cell_t unload_file(base::lisp &gl, base::cell_t, base::cells_t &) { ts.stop(); ts.setSource(nullptr); frs = nullptr; return gl.nil(); } // playback-start base::cell_t start(base::lisp &gl, base::cell_t, base::cells_t &) { ts.start(); return gl.nil(); } // playback-stop base::cell_t stop(base::lisp &gl, base::cell_t, base::cells_t &) { ts.stop(); return gl.nil(); } // playback-seek (float)posSeconds base::cell_t seek(base::lisp &gl, base::cell_t c, base::cells_t &) { if (base::lisp::validate(c, base::cell::list(1), base::cell::typeFloat)) { const auto &pos = c + 1; ts.setPosition((double)pos->f); return gl.nil(); } gl.signalError("playback-seek: invalid arguments, expected (float)"); return gl.nil(); } // playback-length -> (float)/total time in seconds/ base::cell_t length(base::lisp &gl, base::cell_t, base::cells_t &ret) { ret.push_back(base::cell(float(ts.getLengthInSeconds()))); return ret.end(); } // playback-get-pos -> (float)/playback position in seconds/ base::cell_t get_pos(base::lisp &gl, base::cell_t, base::cells_t &ret) { ret.push_back(base::cell(float(ts.getCurrentPosition()))); return ret.end(); } // playback-is-playing -> t/nil base::cell_t is_playing(base::lisp &gl, base::cell_t, base::cells_t &) { if (ts.isPlaying()) return gl.t(); return gl.nil(); } // playback-finished -> t/nil base::cell_t finished_playing(base::lisp &gl, base::cell_t, base::cells_t &) { if (ts.hasStreamFinished()) return gl.t(); return gl.nil(); } // (bind-playback (id)callback) base::cell_t bind_playback(base::lisp &gl, base::cell_t c, base::cells_t &) { if (pl) { if (base::lisp::validate(c, base::cell::list(1), base::cell::typeIdentifier)) { const auto &fx = c + 1; pl->functionId = fx->s; pl->enabled = true; return gl.t(); } pl->enabled = false; return gl.nil(); } gl.signalError("bind-playback: invalid arguments, expected (id)"); return gl.nil(); } // (playback-gain (float|optional)gain) -> t/nil | gain base::cell_t gain(base::lisp &gl, base::cell_t c, base::cells_t &ret) { if (pl) { if (base::lisp::validate(c, base::cell::listRange(1), base::cell::typeFloat)) { // setter ts.setGain((c + 1)->f); return gl.t(); } else if (base::lisp::validate(c, base::cell::list(0))) { // getter ret.push_back(base::cell(ts.getGain())); return ret.end(); } gl.signalError("playback-gain: invalid arguments, expected ((optional) float)"); } return gl.nil(); } // (unbind-playback) base::cell_t unbind_playback(base::lisp &gl, base::cell_t, base::cells_t &) { if (pl) { pl->enabled = false; return gl.t(); } return gl.nil(); } }
bool AudioSourceFilePrelistener::play(const String& absolutePathToAudioFile, const int& startPosition_, const int& endPosition_) { DEB("AudioSourceFilePreview::play called."); // If a new audio file is specified, // delete the old bufferingAudioSource and // create a new bufferingAudioSource if (absolutePathToAudioFile != previouslyUsedPathToAudioFile) { // delete the old audioFormatReaderSource // (exept the first time, when there is no audioFormatReaderSource) if (bufferingAudioSource != NULL) { bufferingAudioSource->releaseResources(); delete bufferingAudioSource; } // \/ \/ \/ Similar to AudioRegionMixer::addRegion \/ \/ \/ // --- begin{audio file stuff} --- File audioFile(absolutePathToAudioFile); // get a format manager and set it up with the basic types (wav and aiff). AudioFormatManager audioFormatManager; audioFormatManager.registerBasicFormats(); // Currently, this registers the WAV and AIFF formats. AudioFormatReader* audioFormatReader = audioFormatManager.createReaderFor (audioFile); // This audioFormatReader will be deleted when the audioFormatReaderSource will // be deleted // --- end{audio file stuff} --- // if the previous lines of code weren't successful if (audioFormatReader == NULL) { DEB("AudioSourceFilePrelistener: The audio file couldn't be read.") delete audioFormatReader; bufferingAudioSource = NULL; runPlayback = false; return false; } // Check if this input set is invalid if (startPosition_ >= endPosition_ || startPosition_ < 0 || endPosition_ > audioFormatReader->lengthInSamples) { DEB("AudioSourceFilePrelistener: Didn't play because the given" "startPosition (" + String(startPosition_) + ") and endPosition (" + String(endPosition_) + ") don't make sense.") delete audioFormatReader; bufferingAudioSource = NULL; runPlayback = false; return false; } // /\ /\ /\ End of similar to AudioRegionMixer::addRegion /\ /\ /\ const bool deleteAudioFormatReaderWhenDeleted = true; AudioFormatReaderSource* audioFormatReaderSource = new AudioFormatReaderSource (audioFormatReader, deleteAudioFormatReaderWhenDeleted); bool deleteSourceWhenDeleted = true; bufferingAudioSource = new BufferingAudioSource (audioFormatReaderSource, deleteSourceWhenDeleted, 32768); bufferingAudioSource->prepareToPlay(samplesPerBlockExpected, sampleRate); } else // if (absolutePathToAudioFile == previouslyUsedPathToAudioFile) { // Check if this input set is invalid if (startPosition_ >= endPosition || startPosition_ < 0 || endPosition_ > bufferingAudioSource->getTotalLength()) { DEB("AudioSourceFilePrelistener: Didn't play because the given" "startPosition (" + String(startPosition_) + ") and endPosition (" + String(endPosition_) + ") don't make sense.") runPlayback = false; return false; } } nextPlayPosition = startPosition_; endPosition = endPosition_; bufferingAudioSource->setNextReadPosition (nextPlayPosition); runPlayback = true; return true; }
bool handlePluginRequest(const PluginRequestParameters ¶ms, OutputStream &ostream, ThreadSafePlugin *plugin = nullptr) { if (!plugin) { // It's very possible that all of this was a premature optimization. // For VSTs at least, code loading and caching is handled by ModuleHandle::findOrCreateModule, // and each instantiation only requires a couple of disc hits for working directory setting. // On the other hand, we want to make sure that each audio request has a "fresh" instance. // The easiest way to do this is by bypassing the instance pool and instantiating on demand. #if PLUGIN_POOL_SIZE // Recurse with a plugin from the pool, locking on it. // Keep trying with a delay until a timeout occurs. const int TIMEOUT = 5000, WAIT = 200; int64 startTime = Time::currentTimeMillis(); while (Time::currentTimeMillis() < startTime + TIMEOUT) { int i = 0; while ((plugin = pluginPool[i++])) { const ScopedTryLock pluginTryLock(plugin->crit); if (pluginTryLock.isLocked()) { DBG << "Handling with plugin " << i << endl; return handlePluginRequest(params, ostream, plugin); } } DBG << "Trying again in " << WAIT << endl; Thread::sleep(WAIT); } // If we were unable to obtain a lock, return failure. DBG << "Timeout" << endl; return false; #else ThreadSafePlugin temporaryPlugin(createSynthInstance()); return handlePluginRequest(params, ostream, &temporaryPlugin); #endif } else { // Re-acquire or acquire the lock. const ScopedLock pluginLock(plugin->crit); AudioPluginInstance *instance = plugin->instance; // unmanaged, for simplicity // Attempt to reset the plugin in all ways possible. instance->reset(); // Setting default parameters here causes miniTERA to become unresponsive to parameter settings. // It's possible that it's effectively pressing some interface buttons that change the editor mode entirely. // It's not necessary anyways if the plugin instance has been freshly created (see above). // pluginParametersOldNewFallback(instance, nullptr, &pluginDefaults); // note that the defaults may be empty instance->setCurrentProgram(0); // Load preset if specified, before listing or modifying parameters! if (params.presetNumber >= 0 && params.presetNumber < instance->getNumPrograms()) { DBG << "Setting program/preset: " << params.presetNumber << endl; instance->setCurrentProgram(params.presetNumber); } int currentProgram = instance->getCurrentProgram(); DBG << "Current program/preset: " << currentProgram << " - " << instance->getProgramName(currentProgram) << endl; // Set parameters, starting with named, then indexed pluginParametersSet(instance, params.parameters); pluginParametersSetIndexed(instance, params.indexedParameters); // If parameters requested, output them and return if (params.listParameters) { DBG << "Rendering parameter list: # parameters " << instance->getNumPrograms() << endl; // Output each parameter setting in two places: // an indexed array and a dictionary by name // All DynamicObjects created will be freed when their var's leave scope. DynamicObject *outer = new DynamicObject(); DynamicObject *innerParams = new DynamicObject(); var indexedParamVar; { for (int i = 0, n = instance->getNumParameters(); i < n; ++i) { String name = instance->getParameterName(i); float val = instance->getParameter(i); innerParams->setProperty(name, val); DynamicObject *indexedInnerObj = new DynamicObject(); indexedInnerObj->setProperty("index", i); indexedInnerObj->setProperty("name", name); indexedInnerObj->setProperty("value", val); indexedParamVar.append(var(indexedInnerObj)); // frees indexedInnerObj when this scope ends } } outer->setProperty(Identifier("parameters"), var(innerParams)); outer->setProperty(Identifier("indexedParameters"), indexedParamVar); // List presets/programs. var progVar; { for (int i = 0, n = instance->getNumPrograms(); i < n; ++i) { progVar.append(var(instance->getProgramName(i))); } } outer->setProperty(Identifier("presets"), progVar); var outerVar(outer); JSON::writeToStream(ostream, outerVar); // DBG << JSON::toString(outerVar, true /* allOnOneLine */) << endl; return true; } // Now attempt to render audio. AudioFormatManager formatManager; formatManager.registerBasicFormats(); OptionalScopedPointer<AudioFormat> outputFormat(formatManager.findFormatForFileExtension(params.getFormatName()), false); if (!outputFormat) return false; instance->setNonRealtime(true); instance->prepareToPlay(params.sampleRate, params.blockSize); instance->setNonRealtime(true); // The writer takes ownership of the output stream; the writer will delete it when the writer leaves scope. // Therefore, we pass a special pointer class that does not allow the writer to delete it. OutputStream *ostreamNonDeleting = new NonDeletingOutputStream(&ostream); ScopedPointer<AudioFormatWriter> writer(outputFormat->createWriterFor(ostreamNonDeleting, params.sampleRate, params.nChannels, params.bitDepth, StringPairArray(), 0)); // Create a MIDI buffer MidiBuffer midiBuffer; midiBuffer.addEvent(MidiMessage::noteOn(params.midiChannel, (uint8)params.midiPitch, (uint8)params.midiVelocity), 0 /* time */); midiBuffer.addEvent(MidiMessage::allNotesOff(params.midiChannel), params.noteSeconds * params.sampleRate); AudioSampleBuffer buffer(params.nChannels, params.blockSize); int numBuffers = (int)(params.renderSeconds * params.sampleRate / params.blockSize); for (int i = 0; i < numBuffers; ++i) { // DBG << "Processing block " << i << "..." << flush; instance->processBlock(buffer, midiBuffer); // DBG << " left RMS level " << buffer.getRMSLevel(0, 0, params.blockSize) << endl; writer->writeFromAudioSampleBuffer(buffer, 0 /* offset into buffer */, params.blockSize); } instance->reset(); return true; } }