Exemplo n.º 1
0
void CWaveInstrument::SetNote(CNote *note)
{
    // Get a list of all attribute nodes and the
    // length of that list
    CComPtr<IXMLDOMNamedNodeMap> attributes;
    note->Node()->get_attributes(&attributes);
    long len;
    attributes->get_length(&len);

    // Loop over the list of attributes
    for(int i=0;  i<len;  i++)
    {
        // Get attribute i
        CComPtr<IXMLDOMNode> attrib;
        attributes->get_item(i, &attrib);

        // Get the name of the attribute
        CComBSTR name;
        attrib->get_nodeName(&name);

        // Get the value of the attribute.  A CComVariant is a variable
        // that can have any type. It loads the attribute value as a
        // string (UNICODE), but we can then change it to an integer 
        // (VT_I4) or double (VT_R8) using the ChangeType function 
        // and then read its integer or double value from a member variable.
        CComVariant value;
        attrib->get_nodeValue(&value);

        if(name == "duration")
        {
            value.ChangeType(VT_R8);
            SetDuration(value.dblVal);
        }
		else if(name == "note")
        {
            m_freq = NoteToFrequency(L"C5") - NoteToFrequency(value.bstrVal);
        }
		else if(name == "measure")
		{
            value.ChangeType(VT_R8);
            if(value.dblVal == 1.0)
			{
				m_attack = 0.04;
				m_release = 0.06;
			}
			else if((value.dblVal - int(value.dblVal)) >= 0)
			{
				m_attack = 0.04;
				m_release = 0.04;
			}
		}
    }
}
void CSubtractiveInstrument::SetNote(CNote *note)
{
	// Get a list of all attribute nodes and the
	// length of that list
	CComPtr<IXMLDOMNamedNodeMap> attributes;
	note->Node()->get_attributes(&attributes);
	long len;
	attributes->get_length(&len);

	StringToWaveform(note->Waveform());

	// Loop over the list of attributes
	for (int i = 0; i < len; i++)
	{
		// Get attribute i
		CComPtr<IXMLDOMNode> attrib;
		attributes->get_item(i, &attrib);

		// Get the name of the attribute
		CComBSTR name;
		attrib->get_nodeName(&name);

		// Get the value of the attribute.  A CComVariant is a variable
		// that can have any type. It loads the attribute value as a
		// string (UNICODE), but we can then change it to an integer 
		// (VT_I4) or double (VT_R8) using the ChangeType function 
		// and then read its integer or double value from a member variable.
		CComVariant value;
		attrib->get_nodeValue(&value);

		if (name == "duration")
		{
			value.ChangeType(VT_R8);
			// number of beats * seconds per beat = seconds for note
			SetDuration(value.dblVal);
		}
		else if (name == "note")
		{
			SetFreq(NoteToFrequency(value.bstrVal));
		}

		if (name == "resonfrequency")
		{
			mResonFilter = true;
			value.ChangeType(VT_R8);
			mResonFrequency = value.dblVal;
		}

//		if (name == "resonbandwidth")
//		{
//			value.ChangeType(VT_R8);
//			mResonBandwidth = value.dblVal;
//		}
//
//		if (name == "filter-envelope")
//		{
//			mFilterEnvelope = true;
//		}
	}
}
Exemplo n.º 3
0
		void StringSynth::PlayNote(Note n) {
			float old_freq = fundamental_frequency;

			float frequency = NoteToFrequency(n);

			TuneToFrequency(frequency);

			Play();
			Pluck(0.5f * active_length, 0.05f);

			std::this_thread::sleep_for(std::chrono::milliseconds(2000));

			Stop();

			TuneToFrequency(old_freq);
		}
Exemplo n.º 4
0
// Calculate the amount of samples for autocorrelation shifting for a given note
SmpLength Autotune::NoteToShift(uint32 sampleFreq, int note, double pitchReference)
//---------------------------------------------------------------------------------
{
	const double fundamentalFrequency = NoteToFrequency((double)note / BINS_PER_NOTE, pitchReference);
	return std::max(Util::Round<SmpLength>((double)sampleFreq / fundamentalFrequency), SmpLength(1));
}
Exemplo n.º 5
0
bool Autotune::Apply(double pitchReference, int targetNote)
//---------------------------------------------------------
{
	if(!CanApply())
	{
		return false;
	}

	const uint32 sampleFreq = sample.GetSampleRate(modType);
	// At the lowest frequency, we get the highest autocorrelation shift amount.
	const SmpLength maxShift = NoteToShift(sampleFreq, START_NOTE, pitchReference);
	if(!PrepareSample(maxShift))
	{
		return false;
	}
	// We don't process the autocorrelation overhead.
	const SmpLength processLength = sampleLength - maxShift;

	// Set up the autocorrelation threads
	SYSTEM_INFO sysInfo;
	GetSystemInfo(&sysInfo);
	const uint32 numProcs = std::max<uint32>(sysInfo.dwNumberOfProcessors, 1);
	const uint32 notesPerThread = (END_NOTE - START_NOTE + 1) / numProcs;
	std::vector<AutotuneThreadData> threadInfo(numProcs);
	std::vector<HANDLE> threadHandles(numProcs);

	for(uint32 p = 0; p < numProcs; p++)
	{
		threadInfo[p].pitchReference = pitchReference;
		threadInfo[p].sampleData = sampleData;
		threadInfo[p].processLength = processLength;
		threadInfo[p].sampleFreq = sampleFreq;
		threadInfo[p].startNote = START_NOTE + p * notesPerThread;
		threadInfo[p].endNote = START_NOTE + (p + 1) * notesPerThread;
		if(p == numProcs - 1)
			threadInfo[p].endNote = END_NOTE;

		threadHandles[p] = mpt::thread(AutotuneThread, &threadInfo[p]);
		ASSERT(threadHandles[p] != INVALID_HANDLE_VALUE);
	}

	WaitForMultipleObjects(numProcs, &threadHandles[0], TRUE, INFINITE);

	// Histogram for all notes.
	std::vector<uint64> autocorrHistogram(HISTORY_BINS, 0);

	for(uint32 p = 0; p < numProcs; p++)
	{
		for(int i = 0; i < HISTORY_BINS; i++)
		{
			autocorrHistogram[i] += threadInfo[p].histogram[i];
		}
		CloseHandle(threadHandles[p]);
	}

	// Interpolate the histogram...
	std::vector<uint64> interpolatedHistogram(HISTORY_BINS, 0);
	for(int i = 0; i < HISTORY_BINS; i++)
	{
		interpolatedHistogram[i] = autocorrHistogram[i];
		const int kernelWidth = 4;
		for(int ki = kernelWidth; ki >= 0; ki--)
		{
			// Choose bins to interpolate with
			int left = i - ki;
			if(left < 0) left += HISTORY_BINS;
			int right = i + ki;
			if(right >= HISTORY_BINS) right -= HISTORY_BINS;

			interpolatedHistogram[i] = interpolatedHistogram[i] / 2 + (autocorrHistogram[left] + autocorrHistogram[right]) / 2;
		}
	}

	// ...and find global minimum
	int minimumBin = 0;
	for(int i = 0; i < HISTORY_BINS; i++)
	{
		const int prev = (i > 0) ? (i - 1) : (HISTORY_BINS - 1);
		// Are we at the global minimum?
		if(interpolatedHistogram[prev] < interpolatedHistogram[minimumBin])
		{
			minimumBin = prev;
		}
	}

	// Center target notes around C
	if(targetNote >= 6)
	{
		targetNote -= 12;
	}

	// Center bins around target note
	minimumBin -= targetNote * BINS_PER_NOTE;
	if(minimumBin >= 6 * BINS_PER_NOTE)
	{
		minimumBin -= 12 * BINS_PER_NOTE;
	}
	minimumBin += targetNote * BINS_PER_NOTE;

	const double newFundamentalFreq = NoteToFrequency(static_cast<double>(69 - targetNote) + static_cast<double>(minimumBin) / BINS_PER_NOTE, pitchReference);

	sample.nC5Speed = Util::Round<uint32>(sample.nC5Speed * pitchReference / newFundamentalFreq);

	if((modType & (MOD_TYPE_XM | MOD_TYPE_MOD)) != 0)
	{
		sample.FrequencyToTranspose();
		if((modType & MOD_TYPE_MOD) != 0)
		{
			sample.RelativeTone = 0;
		}
	}

	return true;
}
Exemplo n.º 6
0
    //--------------------------------------------------------------------------------------------------
    void OnKey (char key, bool pressed) {

        // pressing numbers switches instruments
        if (pressed) {
            switch (key)
            {
                case '1': g_currentWaveForm = e_waveSine; ReportParams(); return;
                case '2': g_currentWaveForm = e_waveSaw; ReportParams(); return;
                case '3': g_currentWaveForm = e_waveSquare; ReportParams(); return;
                case '4': g_currentWaveForm = e_waveTriangle; ReportParams(); return;
                case '5': g_currentDelay = e_delayNone; ReportParams(); return;
                case '6': g_currentDelay = e_delay1; ReportParams(); return;
                case '7': g_currentDelay = e_delay2; ReportParams(); return;
                case '8': g_currentDelay = e_delay3; ReportParams(); return;
                case '9': {
                    std::lock_guard<std::mutex> guard(g_notesMutex);
                    g_notes.push_back(SNote(0.0f, e_sampleCymbals));
                    return;
                }
                case '0': {
                    std::lock_guard<std::mutex> guard(g_notesMutex);
                    g_notes.push_back(SNote(0.0f, e_sampleVoice));
                    return;
                }
            }
        }

        // figure out what frequency to play
        float frequency = 0.0f;
        switch (key) {

            // QWERTY row
            case 'Q': frequency = NoteToFrequency(3, 0); break;
            case 'W': frequency = NoteToFrequency(3, 1); break;
            case 'E': frequency = NoteToFrequency(3, 2); break;
            case 'R': frequency = NoteToFrequency(3, 3); break;
            case 'T': frequency = NoteToFrequency(3, 4); break;
            case 'Y': frequency = NoteToFrequency(3, 5); break;
            case 'U': frequency = NoteToFrequency(3, 6); break;
            case 'I': frequency = NoteToFrequency(3, 7); break;
            case 'O': frequency = NoteToFrequency(3, 8); break;
            case 'P': frequency = NoteToFrequency(3, 9); break;
            case -37: frequency = NoteToFrequency(3, 10); break;

            // ASDF row
            case 'A': frequency = NoteToFrequency(2, 0); break;
            case 'S': frequency = NoteToFrequency(2, 1); break;
            case 'D': frequency = NoteToFrequency(2, 2); break;
            case 'F': frequency = NoteToFrequency(2, 3); break;
            case 'G': frequency = NoteToFrequency(2, 4); break;
            case 'H': frequency = NoteToFrequency(2, 5); break;
            case 'J': frequency = NoteToFrequency(2, 6); break;
            case 'K': frequency = NoteToFrequency(2, 7); break;
            case 'L': frequency = NoteToFrequency(2, 8); break;
            case -70: frequency = NoteToFrequency(2, 9); break;
            case -34: frequency = NoteToFrequency(2, 10); break;

            // ZXCV row
            case 'Z': frequency = NoteToFrequency(1, 0); break;
            case 'X': frequency = NoteToFrequency(1, 1); break;
            case 'C': frequency = NoteToFrequency(1, 2); break;
            case 'V': frequency = NoteToFrequency(1, 3); break;
            case 'B': frequency = NoteToFrequency(1, 4); break;
            case 'N': frequency = NoteToFrequency(1, 5); break;
            case 'M': frequency = NoteToFrequency(1, 6); break;
            case -68: frequency = NoteToFrequency(1, 7); break;
            case -66: frequency = NoteToFrequency(1, 8); break;
            case -65: frequency = NoteToFrequency(1, 9); break;
            case -95: frequency = NoteToFrequency(1, 10); break;  // right shift

            // left shift = low freq
            case 16: frequency = NoteToFrequency(0, 5); break;

            // left shift = low freq
            case -94: frequency = NoteToFrequency(0, 0); break;

            default: {
                return;
            }
        }

        // if releasing a note, we need to find and kill the flute note of the same frequency
        if (!pressed) {
            StopNote(frequency);
            return;
        }

        // get a lock on our notes vector and add the new note
        std::lock_guard<std::mutex> guard(g_notesMutex);
        g_notes.push_back(SNote(frequency, g_currentWaveForm));
    }
Exemplo n.º 7
0
		void StringSynth::TuneToNote(Note n) {
			TuneToFrequency(NoteToFrequency(n));
		}