public void NoteOn(byte num, byte key, byte velocity) { try { Instrument instrument = instrumentTable[new Tuple <byte, byte>(Bank, Instrument)]; int value = instrument.GetSampleEntry(key).Value; Sample sample = soundData.SampleBanks[soundData.InstrumentBanks[Bank].Wsys][(short)instrument.Samples[value].Id]; AudioBuffer audioBuffer = new AudioBuffer(); audioBuffer.AudioBytes = sample.Data.Length; audioBuffer.Stream = new DataStream(sample.Data.Length, canRead: true, canWrite: true); audioBuffer.Stream.Write(sample.Data, 0, sample.Data.Length); audioBuffer.PlayBegin = 0; audioBuffer.PlayLength = 0; audioBuffer.LoopCount = (sample.IsLooping ? 255 : 0); audioBuffer.LoopBegin = sample.LoopStart; audioBuffer.LoopLength = 0; WaveFormat sourceFormat = new WaveFormat(sample.SamplesPerSecond, sample.BitsPerSample, sample.Channels); SourceVoice sourceVoice = new SourceVoice(engine, sourceFormat, VoiceFlags.None, 1024f); sourceVoice.SetOutputVoices(new VoiceSendDescriptor(submix)); sourceVoice.SubmitSourceBuffer(audioBuffer, null); float num2 = XAudio2.SemitonesToFrequencyRatio((!instrument.IsPercussion) ? (key - sample.RootKey) : 0) * instrument.Samples[value].FrequenyMultiplier * instrument.FrequencyMultiplier; sourceVoice.SetFrequencyRatio(num2); sourceVoice.SetVolume(ValueToAmplitude(velocity)); NoteData noteData = new NoteData(sourceVoice, num2, velocity, instrument.IsPercussion); if (instrument.IsPercussion) { noteData.PercussionPan = instrument.Samples[value].Pan.Value; sbyte b = (sbyte)(noteData.PercussionPan - 63); sourceVoice.SetOutputMatrix(1, 2, new float[2] { 0.5f - (float)b / 127f, 0.5f + (float)b / 127f }); } else { sourceVoice.SetOutputMatrix(1, 2, outputMatrix); } noteData.BufferStream = audioBuffer.Stream; noteData.Voice.Start(); voiceTable.Add(num, noteData); sourceFormat = null; GC.Collect(); } catch { } }
/// <summary> /// Start to play a note, It will be stopped until you call "StopNote" /// </summary> /// <param name="notePitch"></param> public void PlayNote(int notePitch) { var asy = Task.Run(() => { if ((Voice == null) || (Instrument == null)) { return; } //If we play another note if ((notePitch != PlayingPitch) || !IsPlaying || stopping) { //Get the frequenc y of the pitch var FrequencyRatio = XAudio2.SemitonesToFrequencyRatio(notePitch) / 2f; //See if we should use another sample var reloadNeeded = Instrument.ReloadNeeded(FrequencyRatio, ActualFrequencyRatio); if (Instrument.IsPlugged || reloadNeeded || !IsPlaying || stopping) { ReloadBuffer(FrequencyRatio, reloadNeeded); } CancelStop.Set(); //Set the frequency ratio to the voice var realFrequencyRatio = Instrument.GetCorrectFrequencyRatio(FrequencyRatio); Voice.SetFrequencyRatio(realFrequencyRatio); ActualFrequencyRatio = FrequencyRatio; PlayingPitch = notePitch; } //Start the play if needed if (!IsPlaying) { Voice.Start(); Voice.SetVolume(1, XAudio2.CommitNow); } //update state IsPlaying = true; }); }
public float SemitonesToFrequencyRatio(float semitones) { return(XAudio2.SemitonesToFrequencyRatio(semitones)); }
/// <summary> /// Sets the frequency of the sound. /// </summary> /// <param name="f">The frequency ratio of the sound expressed in semitones.</param> public void setFrequency(float f) { voice.SetFrequencyRatio(XAudio2.SemitonesToFrequencyRatio(f)); }