Exemplo n.º 1
0
    //==============================================================================
    void startRecording (const File& file)
    {
        stop();

        if (sampleRate > 0)
        {
            // Create an OutputStream to write to our destination file...
            file.deleteFile();
            ScopedPointer<FileOutputStream> fileStream (file.createOutputStream());

            if (fileStream != 0)
            {
                // Now create a WAV writer object that writes to our output stream...
                WavAudioFormat wavFormat;
                AudioFormatWriter* writer = wavFormat.createWriterFor (fileStream, sampleRate, 1, 16, StringPairArray(), 0);

                if (writer != 0)
                {
                    fileStream.release(); // (passes responsibility for deleting the stream to the writer object that is now using it)

                    // Now we'll create one of these helper objects which will act as a FIFO buffer, and will
                    // write the data to disk on our background thread.
                    threadedWriter = new AudioFormatWriter::ThreadedWriter (writer, backgroundThread, 32768);

                    // And now, swap over our active writer pointer so that the audio callback will start using it..
                    const ScopedLock sl (writerLock);
                    activeWriter = threadedWriter;
                }
            }
        }
    }
Exemplo n.º 2
0
void AudioRecorder::startRecording(const File& file){
        stop();
        if (sampleRate > 0) {
            file.deleteFile();
            ScopedPointer<FileOutputStream> fileStream(file.createOutputStream());
            if (fileStream != nullptr) {
                WavAudioFormat wavFormat;
                AudioFormatWriter* writer = wavFormat.createWriterFor(fileStream,
                                                                      sampleRate, 1, 16, StringPairArray(), 0);
                if (writer != nullptr) {
                    fileStream.release();
                    threadedWriter = new AudioFormatWriter::ThreadedWriter(writer,
                                                                           backgroundThread, 32768);
                   // thumbnail.reset(writer->getNumChannels(), writer->getSampleRate());
                    nextSampleNum = 0;
                    const ScopedLock sl(writerLock);
                    activeWriter = threadedWriter;
                }
            }
        }
    }
Exemplo n.º 3
0
void MainContentComponent::buttonClicked (Button* buttonThatWasClicked)
{
    //[UserbuttonClicked_Pre]
    //[/UserbuttonClicked_Pre]

    if (buttonThatWasClicked == convButton)
    {
        //[UserButtonCode_convButton] -- add your button handler code here..
		const ScopedLock fl(soundListLock);

		setPlayheadUiEnabled(false);

		bool convValid = true;

		float q;
		float s;
		double nfft;
		{
			const ScopedLock pl(paramLock);
			q = qParam;
			s = sParam;
			nfft = static_cast<double>(nfftParam);
		}

		int fftInputLen = static_cast<int>(std::pow(2.0, nfft));
		int fftOutputLen = fftInputLen / 2 + 1;
		int numChannels = 1;

		unordered_set<int> includedSounds;
		int maxChannels = 0;
		float pSum = 0.0f;
		float rSum = 0.0f;
		for (const auto& iter : idToSound) {
			int id = iter.first;
			Sound* sound = iter.second.get();
			int numChannels = sound->getBufferNumChannels();
			if (sound->isIncluded() && numChannels > 0) {
				maxChannels = numChannels > maxChannels ? numChannels : maxChannels;
				includedSounds.emplace(id);
				pSum += static_cast<float>(sound->getPValue());
				rSum += static_cast<float>(sound->getRValue());
			}
		}
		float n = static_cast<float>(includedSounds.size());
		float pScale = n * q / pSum;
		float rScale = n * s / rSum;

		if (maxChannels == 0) {
			return;
		}

		kiss_fftr_state* fftInverseState = kiss_fftr_alloc(fftInputLen, 1, nullptr, nullptr);
		kiss_fft_cpx* CONV = static_cast<kiss_fft_cpx*>(calloc(fftOutputLen * maxChannels, sizeof(kiss_fft_cpx)));
		conv.setSize(maxChannels, fftInputLen);

		float max = -1.0f;

		// convolve
		for (int convChannel = 0; convChannel < maxChannels; ++convChannel) {
			kiss_fft_cpx* CONVCHANNEL = CONV + (convChannel * fftOutputLen);

			bool isFirstSound = true;
			for (const auto& id : includedSounds) {
				Sound* sound = idToSound[id].get();
				jassert(sound != nullptr);
				float p = pScale * static_cast<float>(sound->getPValue());
				float r = rScale * static_cast<float>(sound->getRValue());
				int soundNumChannels = sound->getBufferNumChannels();
				int soundNumSamples = sound->getBufferNumSamples();
				int soundChannel = convChannel >= soundNumChannels ? soundNumChannels - 1 : convChannel;
				const kiss_fft_cpx* SOUNDCHANNEL = sound->getSpectra(fftInputLen, soundChannel);

				for (int i = 0; i < fftOutputLen; ++i) {
					float xr = SOUNDCHANNEL[i].r;
					float xi = SOUNDCHANNEL[i].i;
					float xMag = sqrtf((xr * xr) + (xi * xi));
					float xPhs = atan2f(xi, xr);
					float convMag = powf(xMag, p);
					float convPhs = r * xPhs;
					float convr = convMag * cosf(convPhs);
					float convi = convMag * sinf(convPhs);

					if (std::isnan(convr) || std::isnan(convi)) {
						convValid = false;
					}

					if (isFirstSound) {
						CONVCHANNEL[i].r = convr;
						CONVCHANNEL[i].i = convi;
					}
					else {
						float a = CONVCHANNEL[i].r;
						float b = CONVCHANNEL[i].i;
						float c = convr;
						float d = convi;
						CONVCHANNEL[i].r = a * c - b * d;
						CONVCHANNEL[i].i = a * d + b * c;
					}
				}

				isFirstSound = false;
			}

			// ifft
			kiss_fftri(fftInverseState, CONVCHANNEL, conv.getWritePointer(convChannel));

			// check max
			float channelMax = conv.findMinMax(convChannel, 0, fftInputLen).getEnd();
			max = channelMax > max ? channelMax : max;
		}

		delete fftInverseState;
		delete CONV;

		// normalize
		conv.applyGain(1.0f / max);

		if (!convValid) {
			AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Error", "Parameters produced NaN value.");
			return;
		}

		setPlayheadAudio(&conv);
        //[/UserButtonCode_convButton]
    }
    else if (buttonThatWasClicked == settingsButton)
    {
        //[UserButtonCode_settingsButton] -- add your button handler code here..
		AudioDeviceSelectorComponent audioSettingsComp(deviceManager,
			0, 256,
			0, 256,
			true, true, true, false);

		audioSettingsComp.setSize(500, 450);

		DialogWindow::LaunchOptions o;
		o.content.setNonOwned(&audioSettingsComp);
		o.dialogTitle = "Audio Settings";
		o.componentToCentreAround = this;
		o.dialogBackgroundColour = Colours::azure;
		o.escapeKeyTriggersCloseButton = true;
		o.useNativeTitleBar = false;
		o.resizable = false;

		o.runModal();

		ScopedPointer<XmlElement> audioState(deviceManager.createStateXml());

		getAppProperties().getUserSettings()->setValue("audioDeviceState", audioState);
		getAppProperties().getUserSettings()->saveIfNeeded();
        //[/UserButtonCode_settingsButton]
    }
    else if (buttonThatWasClicked == playButton)
    {
        //[UserButtonCode_playButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);
		playheadState = PlayheadState::playing;
		playheadAudioSamplesCompleted = 0;
        //[/UserButtonCode_playButton]
    }
    else if (buttonThatWasClicked == loopButton)
    {
        //[UserButtonCode_loopButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);
		playheadState = PlayheadState::looping;
        //[/UserButtonCode_loopButton]
    }
    else if (buttonThatWasClicked == stopButton)
    {
        //[UserButtonCode_stopButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);
		playheadState = PlayheadState::stopped;
		playheadAudioSamplesCompleted = 0;
        //[/UserButtonCode_stopButton]
    }
    else if (buttonThatWasClicked == qDefaultButton)
    {
        //[UserButtonCode_qDefaultButton] -- add your button handler code here..
		qSlider->setValue(1.0);
        //[/UserButtonCode_qDefaultButton]
    }
    else if (buttonThatWasClicked == sDefaultButton)
    {
        //[UserButtonCode_sDefaultButton] -- add your button handler code here..
		sSlider->setValue(1.0);
        //[/UserButtonCode_sDefaultButton]
    }
    else if (buttonThatWasClicked == saveButton)
    {
        //[UserButtonCode_saveButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);

		if (playheadAudio.getNumChannels() > 0 && playheadAudio.getNumSamples() > 0) {
			FileChooser fileChooser("Save as...", File::nonexistent, "*.wav", true);
			if (fileChooser.browseForFileToSave(true)) {
				File outputFile = fileChooser.getResult();
				outputFile.deleteFile();
				WavAudioFormat wavFormat;
				ScopedPointer<FileOutputStream> outputFileStream = outputFile.createOutputStream();
				ScopedPointer<AudioFormatWriter> writer = wavFormat.createWriterFor(outputFileStream, 44100.0, playheadAudio.getNumChannels(), 16, StringPairArray(), 0);
				writer->writeFromAudioSampleBuffer(playheadAudio, 0, playheadAudio.getNumSamples());
				outputFileStream.release();
			}
		}
        //[/UserButtonCode_saveButton]
    }
    else if (buttonThatWasClicked == inputRemoveButton)
    {
        //[UserButtonCode_inputRemoveButton] -- add your button handler code here..
		const ScopedLock fl(soundListLock);
		SparseSet<int> selectedRows = inputFileListComponent->getSelectedRows();
		for (int i = 0; i < selectedRows.size(); ++i) {
			int row = selectedRows[i];
			int id = inputFileListComponent->getIdForRow(row);
			const auto& iter = idToSound.find(id);
			jassert(iter != idToSound.end());
			idToSound.erase(iter);
		}
		if (selectedRows.size() > 0) {
			inputFilesChanged(dontSendNotification);
		}
        //[/UserButtonCode_inputRemoveButton]
    }
    else if (buttonThatWasClicked == inputAddButton)
    {
        //[UserButtonCode_inputAddButton] -- add your button handler code here..
		const ScopedLock fl(soundListLock);
		FileChooser fileChooser("Add sound...", File::nonexistent, "*.wav;*.aif;*.aiff;*.ogg", true);
		if (fileChooser.browseForMultipleFilesToOpen()) {
			Array<File> files = fileChooser.getResults();
			StringArray filePaths;
			for (int i = 0; i < files.size(); ++i) {
				filePaths.add(files[i].getFullPathName());
			}
			filesDropped(filePaths, -1, -1);
		}
        //[/UserButtonCode_inputAddButton]
    }

    //[UserbuttonClicked_Post]
    //[/UserbuttonClicked_Post]
}
Exemplo n.º 4
0
/*
	Start recording to a specified file
	*/
void Audio::AudioRecorder::startRecording (const File& file)
{
    // make sure recorder is stopped first
    stop();
    if (sampleRate > 0)
    {
        // delete file contents first
        file.deleteFile();
        // create file stream for file
        ScopedPointer<FileOutputStream> fileStream (file.createOutputStream());
        
        if (fileStream != nullptr)
        {
            // create a wav format writer
            WavAudioFormat wavFormat;
            AudioFormatWriter* writer = wavFormat.createWriterFor (fileStream, sampleRate, 1, 16, StringPairArray(), 0);
            
            if (writer != nullptr)
            {
                fileStream.release();
                
                // create a thread for the writer.
                threadedWriter = new AudioFormatWriter::ThreadedWriter (writer, backgroundThread, 32768);
                
                // set the next sample number to start
                nextSampleNum = 0;
                
                // scoped lock for writer
                const ScopedLock sl (writerLock);
                activeWriter = threadedWriter;
            }
        }
    }
}
Exemplo n.º 5
0
    void testNodeStore (String type,
                        bool const useEphemeralDatabase,
                        bool const testPersistence,
                        int64 const seedValue,
                        int numObjectsToTest = 2000)
    {
        DummyScheduler scheduler;

        String s;
        s << String ("NodeStore backend '") + type + "'";
        if (useEphemeralDatabase)
            s << " (with ephemeral database)";

        beginTestCase (s);

        File const node_db (File::createTempFile ("node_db"));
        StringPairArray nodeParams;
        nodeParams.set ("type", type);
        nodeParams.set ("path", node_db.getFullPathName ());

        File const temp_db  (File::createTempFile ("temp_db"));
        StringPairArray tempParams;
        if (useEphemeralDatabase)
        {
            tempParams.set ("type", type);
            tempParams.set ("path", temp_db.getFullPathName ());
        }

        // Create a batch
        Batch batch;
        createPredictableBatch (batch, 0, numObjectsToTest, seedValue);

        {
            // Open the database
            ScopedPointer <Database> db (Database::New ("test", scheduler, nodeParams, tempParams));

            // Write the batch
            storeBatch (*db, batch);

            {
                // Read it back in
                Batch copy;
                fetchCopyOfBatch (*db, &copy, batch);
                expect (areBatchesEqual (batch, copy), "Should be equal");
            }

            {
                // Reorder and read the copy again
                Batch copy;
                UnitTestUtilities::repeatableShuffle (batch.size (), batch, seedValue);
                fetchCopyOfBatch (*db, &copy, batch);
                expect (areBatchesEqual (batch, copy), "Should be equal");
            }
        }

        if (testPersistence)
        {
            {
                // Re-open the database without the ephemeral DB
                ScopedPointer <Database> db (Database::New ("test", scheduler, nodeParams));

                // Read it back in
                Batch copy;
                fetchCopyOfBatch (*db, &copy, batch);

                // Canonicalize the source and destination batches
                std::sort (batch.begin (), batch.end (), NodeObject::LessThan ());
                std::sort (copy.begin (), copy.end (), NodeObject::LessThan ());
                expect (areBatchesEqual (batch, copy), "Should be equal");
            }

            if (useEphemeralDatabase)
            {
                // Verify the ephemeral db
                ScopedPointer <Database> db (Database::New ("test",
                    scheduler, tempParams, StringPairArray ()));

                // Read it back in
                Batch copy;
                fetchCopyOfBatch (*db, &copy, batch);

                // Canonicalize the source and destination batches
                std::sort (batch.begin (), batch.end (), NodeObject::LessThan ());
                std::sort (copy.begin (), copy.end (), NodeObject::LessThan ());
                expect (areBatchesEqual (batch, copy), "Should be equal");
            }
        }
    }