Exemplo n.º 1
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.º 2
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.º 3
0
BEGIN_UGEN_NAMESPACE

#include "ugen_DiskOut.h"
#include "../ugen_JuceUtility.h"


DiskOutUGenInternal::DiskOutUGenInternal(File const& file, UGen const& input, bool overwriteExisitingFile, int bitDepth) throw()
:	ProxyOwnerUGenInternal(NumInputs, input.getNumChannels()-1),
	audioFormatWriter(0),
	bufferData(0),
	numInputChannels(input.getNumChannels())
{
	ugen_assert(bitDepth >= 16);
	
	inputs[Input] = input;
	
	bufferData = new float*[numInputChannels];
	memset(bufferData, 0, numInputChannels * sizeof(float*));
	
	File outputFile(file);
	
	if(outputFile.getFileExtension().isEmpty())
		outputFile = outputFile.withFileExtension("wav");
	
	if(overwriteExisitingFile == true && outputFile.exists())
		outputFile.deleteFile();
	else if(outputFile.exists())
	{
		ugen_assertfalse;
		return;
	}
	
	if(outputFile.hasFileExtension(".wav"))
	{
		WavAudioFormat wavAudioFormat;
		FileOutputStream* fileOutputStream = outputFile.createOutputStream();
		
		if(fileOutputStream)
			audioFormatWriter = wavAudioFormat.createWriterFor(fileOutputStream, 
															   UGen::getSampleRate(), 
															   numInputChannels, 
															   bitDepth, 0, 0);
	}
	else if(outputFile.hasFileExtension(".aif") 
			|| outputFile.hasFileExtension(".aiff"))
	{
		AiffAudioFormat aiffAudioFormat;
		FileOutputStream* fileOutputStream = outputFile.createOutputStream();
		
		if(fileOutputStream)
			audioFormatWriter = aiffAudioFormat.createWriterFor(fileOutputStream, 
																UGen::getSampleRate(), 
																numInputChannels, 
																bitDepth, 0, 0);
	}
		
}
    Writer (OutputStream* destStream, const String& formatName,
            const File& lameApp, int vbr, int cbr,
            double sampleRate, unsigned int numberOfChannels,
            unsigned int bitsPerSample, const StringPairArray& metadata)
        : AudioFormatWriter (destStream, formatName, sampleRate,
                             numberOfChannels, bitsPerSample),
          vbrLevel (vbr), cbrBitrate (cbr),
          tempWav (".wav")
    {
        WavAudioFormat wavFormat;

        if (FileOutputStream* out = tempWav.getFile().createOutputStream())
        {
            writer = wavFormat.createWriterFor (out, sampleRate, numChannels,
                                                bitsPerSample, metadata, 0);

            args.add (lameApp.getFullPathName());

            args.add ("--quiet");

            if (cbrBitrate == 0)
            {
                args.add ("--vbr-new");
                args.add ("-V");
                args.add (String (vbrLevel));
            }
            else
            {
                args.add ("--cbr");
                args.add ("-b");
                args.add (String (cbrBitrate));
            }

            addMetadataArg (metadata, "id3title",       "--tt");
            addMetadataArg (metadata, "id3artist",      "--ta");
            addMetadataArg (metadata, "id3album",       "--tl");
            addMetadataArg (metadata, "id3comment",     "--tc");
            addMetadataArg (metadata, "id3date",        "--ty");
            addMetadataArg (metadata, "id3genre",       "--tg");
            addMetadataArg (metadata, "id3trackNumber", "--tn");
        }
    }
Exemplo n.º 5
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.º 6
0
		virtual void menuItemSelected(int menuItemID, int)
		{
			if (menuItemID == 200)
			{
				WildcardFileFilter wildcardFilter("*.mid", String::empty, "Midi files");
				FileBrowserComponent browser(FileBrowserComponent::canSelectFiles | FileBrowserComponent::openMode, 
					lastOpenedFile.exists() ? lastOpenedFile : File(String("C:\\Users\\GeorgeKrueger\\Documents")), &wildcardFilter, nullptr);
				FileChooserDialogBox dialogBox("Open a midi file",
					"Please choose a midi file to open...",
					browser,
					false,
					Colours::lightgrey);

				if (dialogBox.show())
				{
					File selectedFile = browser.getSelectedFile(0);
					lastOpenedFile = selectedFile;
					FileInputStream fileStream(selectedFile);
					juce::MidiFile midiFile;
					midiFile.readFrom(fileStream);
					int numTracks = midiFile.getNumTracks();
					midiFile.convertTimestampTicksToSeconds();
					String msg;
					msg << "Opened midi file: " << selectedFile.getFileName() << " Tracks: " << numTracks << "\n";
					log(msg);

					for (int i = 0; i < numTracks; ++i)
					{
						const MidiMessageSequence* msgSeq = midiFile.getTrack(i);
						
						OwnedArray<PluginDescription> results;
						String plugFile = "C:\\VST\\FMMF.dll";
						VSTPluginFormat vstFormat;
						vstFormat.findAllTypesForFile(results, plugFile);
						if (results.size() > 0) {
							msg.clear();
							msg << "Found " << results.size() << " plugin(s) matching file " << plugFile << "\n";
							log(msg);

							int secsToRender = 10;
							double sampleRate = 44100;
							int totalSizeInSamples = static_cast<int>(44100 * secsToRender);
							AudioPluginInstance* plugInst = vstFormat.createInstanceFromDescription(*results[0], sampleRate, totalSizeInSamples);
							if (!plugInst) {
								msg.clear();
								msg << "Failed to load plugin " << plugFile << "\n";
								log(msg);
								continue;
							}

							int numInputChannels = plugInst->getTotalNumInputChannels();
							int numOutputChannels = plugInst->getTotalNumOutputChannels();
							msg.clear();
							msg << "Plugin input channels: " << numInputChannels << " output channels: " << numOutputChannels 
								<< " Current program: " << plugInst->getCurrentProgram() << "\n";
							log(msg);

							int maxChannels = std::max(numInputChannels, numOutputChannels);
							AudioBuffer<float> buffer(maxChannels, totalSizeInSamples);
							
							MidiBuffer midiMessages;
							for (int j = 0; j < msgSeq->getNumEvents(); ++j)
							{
								MidiMessageSequence::MidiEventHolder* midiEventHolder = msgSeq->getEventPointer(j);
								MidiMessage midiMsg = midiEventHolder->message;
								int samplePos = static_cast<int>(midiMsg.getTimeStamp() * sampleRate);
								midiMessages.addEvent(midiMsg, samplePos);
							}

							plugInst->prepareToPlay(sampleRate, totalSizeInSamples);
							plugInst->processBlock(buffer, midiMessages);

							/*File txtOutFile("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\soundserver2\\out.txt");
							FileOutputStream* txtOutStream = txtOutFile.createOutputStream();
							for (int j = 0; j < 44100; ++j)
							{
								float sample = buffer.getSample(0, j);
								txtOutStream->writeFloat(sample);
								txtOutStream->writeText(" ", true, false);
							}*/

							File outputFile("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\soundserver2\\out.wav");
							if (outputFile.exists()) {
								outputFile.deleteFile();
							}
							FileOutputStream* fileOutputStream = outputFile.createOutputStream();
							WavAudioFormat wavFormat;
							StringPairArray metadataValues;
							juce::AudioFormatWriter* wavFormatWriter = wavFormat.createWriterFor(
								fileOutputStream, sampleRate, 2, 16, metadataValues, 0);
							bool writeAudioDataRet = wavFormatWriter->writeFromAudioSampleBuffer(buffer, 0, buffer.getNumSamples());
							wavFormatWriter->flush();

							msg.clear();
							msg << "Done writing to output file " << outputFile.getFileName() << " . Write return value: " 
								<< (int)writeAudioDataRet << "\n";
							log(msg);

							delete wavFormatWriter;
							delete plugInst;
						}
						else {
							msg.clear();
							msg << "Could not find plugin from file " << plugFile << "\n";
							log(msg);
						}
					}
				}
			}
		}
void MedianSeparator::writeFiles()
{

	ScopedPointer<ISTFT> istft = new ISTFT();
	istft->initWindow(1);

	// Matrices to hold real number data after conversion
	Eigen::MatrixXf harmonicSpectrogramReal_Left;
	Eigen::MatrixXf harmonicSpectrogramReal_Right;
	Eigen::MatrixXf percussiveSpectrogramReal_Left;
	Eigen::MatrixXf percussiveSpectrogramReal_Right;

	// initialise with zeros
	harmonicSpectrogramReal_Left = MatrixXf::Zero(WINDOW_SIZE, numCols);
	harmonicSpectrogramReal_Right = MatrixXf::Zero(WINDOW_SIZE, numCols);
	percussiveSpectrogramReal_Left = MatrixXf::Zero(WINDOW_SIZE, numCols);
	percussiveSpectrogramReal_Right = MatrixXf::Zero(WINDOW_SIZE, numCols);

	// convert complex spectrogram data to real spectrogram data
	harmonicSpectrogramReal_Left = istft->complexToReal(resynthSpectrogram_H[0]);
	harmonicSpectrogramReal_Right = istft->complexToReal(resynthSpectrogram_H[1]);
	percussiveSpectrogramReal_Left = istft->complexToReal(resynthSpectrogram_P[0]);
	percussiveSpectrogramReal_Right = istft->complexToReal(resynthSpectrogram_P[1]);

	// arrays to hold output signals for harmonic and percussive files
	Array<float> outputSignal_P[2];
	Array<float> outputSignal_H[2];

	// fill with zeros (faster than looping through)
	outputSignal_P[0].insertMultiple(0, 0.0f, numSamples);
	outputSignal_P[1].insertMultiple(0, 0.0f, numSamples);
	outputSignal_H[0].insertMultiple(0, 0.0f, numSamples);
	outputSignal_H[1].insertMultiple(0, 0.0f, numSamples);

	// add-overlap ====================
	int offset = 0;
	float temp_L[WINDOW_SIZE] = {};
	float temp_R[WINDOW_SIZE] = {};
	float ifftResults_Left[WINDOW_SIZE] = {};
	float ifftResults_Right[WINDOW_SIZE] = {};

	// loop through each column in spectrograms
	for (int col = 0; col < numCols; col++)
	{
		// insert 4096 samples into temp arrays from harmonic spectrogram
		for (int row = 0; row < WINDOW_SIZE; row++)
		{
			temp_L[row] = harmonicSpectrogramReal_Left(row, col);
			temp_R[row] = harmonicSpectrogramReal_Right(row, col);
		}

		// inverse short time fourier transform on temp_L and temp_R
		istft->performInverseTransform(temp_L, ifftResults_Left);
		istft->rescale(ifftResults_Left);
		istft->performInverseTransform(temp_R, ifftResults_Right);
		istft->rescale(ifftResults_Right);

		// set values in output signal arrays for Harmonic output signal
		for (int i = 0; i < WINDOW_SIZE; i++)
		{
			outputSignal_H[0].set(offset + i, (outputSignal_H[0][offset + i] + (ifftResults_Left[i] * istft->window[i])));
			outputSignal_H[1].set(offset + i, (outputSignal_H[1][offset + i] + (ifftResults_Right[i] * istft->window[i])));
		}

		// insert 4096 samples into temp arrays from percussive spectrogram
		for (int row = 0; row < WINDOW_SIZE; row++)
		{
			temp_L[row] = percussiveSpectrogramReal_Left(row, col);
			temp_R[row] = percussiveSpectrogramReal_Right(row, col);
		}

		// inverse short time fourier transform on temp arrays
		istft->performInverseTransform(temp_L, ifftResults_Left);
		istft->rescale(ifftResults_Left);
		istft->performInverseTransform(temp_R, ifftResults_Right);
		istft->rescale(ifftResults_Right);

		// set values in output arrays for Percussive output signal
		for (int i = 0; i < WINDOW_SIZE; i++)
		{
			outputSignal_P[0].set(offset + i, (outputSignal_P[0][offset + i] + (ifftResults_Left[i] * istft->window[i])));
			outputSignal_P[1].set(offset + i, (outputSignal_P[1][offset + i] + (ifftResults_Right[i] * istft->window[i])));
		}

		offset += HOP_SIZE;	// increment offset by HOP_SIZE (1024)
	}

	//===================================================== WRITE FILES ==
	float gain = 0.5f; // 1.0f divided by num of output files (2)

	AudioSampleBuffer outSamples_H(2, numSamples);
	AudioSampleBuffer outSamples_P(2, numSamples);

	outSamples_H.clear();
	outSamples_P.clear();

	const float* leftData_H = outputSignal_H[0].getRawDataPointer();
	const float* rightData_H = outputSignal_H[1].getRawDataPointer();
	const float* leftData_P = outputSignal_P[0].getRawDataPointer();
	const float* rightData_P = outputSignal_P[1].getRawDataPointer();

	outSamples_H.addFrom(0, 0, leftData_H, numSamples, gain);
	outSamples_H.addFrom(1, 0, rightData_H, numSamples, gain);

	outSamples_P.addFrom(0, 0, leftData_P, numSamples, gain);
	outSamples_P.addFrom(1, 0, rightData_P, numSamples, gain);

	File* outputFile_H = new File(File::getCurrentWorkingDirectory().getChildFile(fileNameNoExt + "_harmonic.wav"));
	File* outputFile_P = new File(File::getCurrentWorkingDirectory().getChildFile(fileNameNoExt + "_percussive.wav"));
	
	if (outputFile_H->exists())
	{
		outputFile_H->deleteFile();
	}

	if (outputFile_P->exists())
	{
		outputFile_P->deleteFile();
	}

	FileOutputStream* output_H;
	FileOutputStream* output_P;

	output_H = outputFile_H->createOutputStream();
	output_P = outputFile_P->createOutputStream();

	// write from sample buffer
	WavAudioFormat* wavFormat = new WavAudioFormat();
	AudioFormatWriter* writer = wavFormat->createWriterFor(output_H, 44100.0, numChannels, 16, NULL, 0);
	writer->flush();
	writer->writeFromAudioSampleBuffer(outSamples_H, 0, numSamples);
	delete writer;

	writer = wavFormat->createWriterFor(output_P, 44100.0, numChannels, 16, NULL, 0);
	writer->flush();
	writer->writeFromAudioSampleBuffer(outSamples_P, 0, numSamples);

	// cleanup
	delete writer;
	delete wavFormat;
	wavFormat = nullptr;
	writer = nullptr;

	outSamples_H.clear();
	outSamples_P.clear();
	outputSignal_H[0].clear();
	outputSignal_H[1].clear();
	outputSignal_P[0].clear();
	outputSignal_P[1].clear();

}
Exemplo n.º 8
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.º 9
0
//==============================================================================
int main (int argc, char* argv[])
{
	if (argc != 3) {
		cout << "Usage: <prog> <midi input file> <wav output file>" << endl;
		return 0;
	}
	File inMidiFile = File(argv[1]);
	File outWavFile = File(argv[2]);

	//File inMidiFile = File("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\pymusic\\out.mid");
	//File outWavFile = File("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\pymusic\\out.wav");

	FileInputStream fileStream(inMidiFile);
	juce::MidiFile midiFile;
	midiFile.readFrom(fileStream);
	int numTracks = midiFile.getNumTracks();
	midiFile.convertTimestampTicksToSeconds();
	std::cout << "Opened midi file: " << inMidiFile.getFileName() << " Tracks: " << numTracks << std::endl;;

	playHead.posInfo.bpm = 120;
	playHead.posInfo.isPlaying = true;
	playHead.posInfo.timeInSamples = 0;
	playHead.posInfo.timeInSeconds = 0;
	playHead.posInfo.timeSigNumerator = 4;
	playHead.posInfo.timeSigDenominator = 4;

	for (int i = 0; i < numTracks; ++i)
	{
		const juce::MidiMessageSequence* msgSeq = midiFile.getTrack(i);

		double trackLengthSeconds = 0;
		String plugFile = "";
		int program = 0;
		for (int j = 0; j < msgSeq->getNumEvents(); ++j)
		{
			juce::MidiMessageSequence::MidiEventHolder* midiEventHolder = msgSeq->getEventPointer(j);
			juce::MidiMessage midiMsg = midiEventHolder->message;
			if (midiMsg.isMetaEvent() && midiMsg.getMetaEventType() == 0x04) {
				// Instrument meta event
				int instrLength = midiMsg.getMetaEventLength();
				const juce::uint8* instrChars = midiMsg.getMetaEventData();
				String instrName((char*)instrChars, instrLength);
				plugFile = instrName;
			}
			if (midiMsg.isMetaEvent() && midiMsg.isEndOfTrackMetaEvent()) {
				//int oetDataLength = midiMsg.getMetaEventLength();
				//const uint8* oetData = midiMsg.getMetaEventData();
				//std::cout << "Found end of track event data size: " << oetDataLength << " data: " << oetData << std::endl;
				trackLengthSeconds = midiMsg.getTimeStamp();
				std::cout << "Track length in seconds: " << trackLengthSeconds << std::endl;
			}
		}

		if (trackLengthSeconds == 0) {
			std::cerr << "Skipping track " << i << " since it has zero length" << std::endl;
			continue;
		}

		if (plugFile.isEmpty()) {
			plugFile = "C:\\VST\\helm.dll";
			std::cout << "No plug found for track. Defaulting to: " << plugFile << std::endl;
			//std::cerr << "Skipping track " << i << ". No instrument found." << std::endl;
			//continue;
		}
		else {
			std::cout << "Found plugin file '" << plugFile << "' from track " << i << std::endl;
		}

		OwnedArray<PluginDescription> results;
		VSTPluginFormat vstFormat;
		vstFormat.findAllTypesForFile(results, plugFile);
		if (results.size() > 0) {
			std::cout << "Found " << results.size() << " plugin(s) in file '" << plugFile << "'" << std::endl;

			int blockSize = 1024;
			double sampleRate = 44100;
			int totalSizeInSamples = ((static_cast<int>(44100 * trackLengthSeconds) / 1024) + 1) * 1024;
			cout << "Total samples to render " << totalSizeInSamples << endl;
			juce::AudioPluginInstance* plugInst = vstFormat.createInstanceFromDescription(*results[0], sampleRate, blockSize);
			if (!plugInst) {
				cout << "Failed to load plugin " << plugFile << endl;
				continue;
			}

			AudioProcessorGraph* graph = new AudioProcessorGraph();
			graph->setPlayConfigDetails(0, 2, sampleRate, blockSize);
			graph->setPlayHead(&playHead);
			graph->addNode(plugInst, 1000);

			int AUDIO_IN_ID = 101;
			int AUDIO_OUT_ID = 102;
			int MIDI_IN_ID = 103;
			juce::AudioPluginInstance* audioInNode = new AudioGraphIOProcessor(AudioGraphIOProcessor::audioInputNode);
			juce::AudioPluginInstance* audioOutNode = new AudioGraphIOProcessor(AudioGraphIOProcessor::audioOutputNode);
			juce::AudioPluginInstance* midiInNode = new AudioGraphIOProcessor(AudioGraphIOProcessor::midiInputNode);
			graph->addNode(audioInNode, AUDIO_IN_ID);
			graph->addNode(audioOutNode, AUDIO_OUT_ID);
			graph->addNode(midiInNode, MIDI_IN_ID);

			graph->addConnection(AUDIO_IN_ID, 0, 1000, 0);
			graph->addConnection(AUDIO_IN_ID, 1, 1000, 1);
			graph->addConnection(MIDI_IN_ID, AudioProcessorGraph::midiChannelIndex, 1000, AudioProcessorGraph::midiChannelIndex);
			graph->addConnection(1000, 0, AUDIO_OUT_ID, 0);
			graph->addConnection(1000, 1, AUDIO_OUT_ID, 1);

			plugInst->setCurrentProgram(program);

			int numInputChannels = plugInst->getTotalNumInputChannels();
			int numOutputChannels = plugInst->getTotalNumOutputChannels();
			cout << "----- Plugin Information -----" << endl;
			cout << "Input channels : " << numInputChannels << endl;
			cout << "Output channels : " << numOutputChannels << endl;
			cout << "Num Programs: " << plugInst->getNumPrograms() << endl;
			cout << "Current program: " << plugInst->getCurrentProgram() << endl;

			int numParams = plugInst->getNumParameters();
			cout << "Num Parameters: " << numParams << endl;
			for (int p = 0; p < numParams; ++p)
			{
				std::cout << "Param " << p << ": " << plugInst->getParameterName(p);
				if (!plugInst->getParameterLabel(p).isEmpty()) {
					cout << "(" << plugInst->getParameterLabel(p) << ")";
				}
				cout << " = " << plugInst->getParameter(p) << endl;
			}
			cout << "-----------------------------" << endl;

			int maxChannels = std::max(numInputChannels, numOutputChannels);
			AudioBuffer<float> entireAudioBuffer(maxChannels, totalSizeInSamples);
			entireAudioBuffer.clear();
			unsigned int midiSeqPos = 0;

			graph->releaseResources();
			graph->prepareToPlay(sampleRate, blockSize);

			cout << "Num midi events: " << msgSeq->getNumEvents() << endl;

			// Render the audio in blocks
			for (int t = 0; t < totalSizeInSamples; t += blockSize)
			{
				//cout << "processing block " << t << " to " << t + blockSize << endl;
				MidiBuffer midiBuffer;
				for (int j = midiSeqPos; j < msgSeq->getNumEvents(); ++j)
				{
					MidiMessageSequence::MidiEventHolder* midiEventHolder = msgSeq->getEventPointer(j);
					MidiMessage midiMsg = midiEventHolder->message;
					int samplePos = static_cast<int>(midiMsg.getTimeStamp() * sampleRate);
					if (samplePos >= t && samplePos < t + blockSize) {
						if (midiMsg.isNoteOnOrOff()) {
							if (midiMsg.isNoteOn()) {
								cout << "note on event (" << midiMsg.getNoteNumber() << ") at " << samplePos << "(" << midiMsg.getTimeStamp() << "s) bufferpos=" << (samplePos - t) << endl;
							}
							else if (midiMsg.isNoteOff()) {
								cout << "note off event (" << midiMsg.getNoteNumber() << ") at " << samplePos << "(" << midiMsg.getTimeStamp() << "s) bufferpos=" << (samplePos - t) << endl;
							}
							midiBuffer.addEvent(midiMsg, samplePos - t);
						}
						else if (midiMsg.isProgramChange()) {
							program = midiMsg.getProgramChangeNumber();
							plugInst->setCurrentProgram(program);
						}
						midiSeqPos++;
					}
					else {
						break;
					}
				}

				playHead.posInfo.timeInSamples = t;
				playHead.posInfo.timeInSeconds = t / sampleRate;

				AudioBuffer<float> blockAudioBuffer(entireAudioBuffer.getNumChannels(), blockSize);
				blockAudioBuffer.clear();
				graph->processBlock(blockAudioBuffer, midiBuffer);

				for (int ch = 0; ch < entireAudioBuffer.getNumChannels(); ++ch) {
					entireAudioBuffer.addFrom(ch, t, blockAudioBuffer, ch, 0, blockSize);
				}
			}

			if (outWavFile.exists()) {
				outWavFile.deleteFile();
			}
			FileOutputStream* fileOutputStream = outWavFile.createOutputStream();
			WavAudioFormat wavFormat;
			StringPairArray metadataValues;
			juce::AudioFormatWriter* wavFormatWriter = wavFormat.createWriterFor(
				fileOutputStream, sampleRate, 2, 16, metadataValues, 0);
			bool writeAudioDataRet = wavFormatWriter->writeFromAudioSampleBuffer(entireAudioBuffer, 0, entireAudioBuffer.getNumSamples());
			wavFormatWriter->flush();

			cout << "Done writing to output file " << outWavFile.getFileName() << " . Write return value: "
				<< (int)writeAudioDataRet << endl;

			delete wavFormatWriter;
		}
		else {
			cerr << "Could not find plugin from file " << plugFile << endl;
		}
	}

    return 0;
}