I would like to play a ring alert without loading/streaming it from file.
Can I embed it's signal or tone in code? I am using NAudio
.
My purpose is improving performance by removing IO actions.
I don't want to use embedded resources.
Only I want generate ring alert in code.
With NAudio you have these options to do that:
- To play a file from a stream (in memory). You have code for this in other answers, actually you do not even need NAudio for this task 'cause
System.Media.SoundPlayer
is enough).
- To generate a signal that will be played (without the need to save it somewhere).
- To play a string of sound commands (somehow as we all did on good old times with
play
in BASIC).
Generate signal
The example for the first case comes from a Charles Petzold article on MSDN (but take a look to NAudio documentation too):
class SineWaveOscillator : WaveProvider16 {
double phaseAngle;
public SineWaveOscillator(int sampleRate):
base(sampleRate, 1) {
}
public double Frequency { set; get; }
public short Amplitude { set; get; }
public override int Read(short[] buffer, int offset,
int sampleCount) {
for (int index = 0; index < sampleCount; index++) {
buffer[offset + index] =
(short)(Amplitude * Math.Sin(phaseAngle));
phaseAngle +=
2 * Math.PI * Frequency / WaveFormat.SampleRate;
if (phaseAngle > 2 * Math.PI)
phaseAngle -= 2 * Math.PI;
}
return sampleCount;
}
}
Then code to play a tone is simple:
SineWaveOscillator osc = new SineWaveOscillator(44100);
osc.Frequency = 440;
osc.Amplitude = 8192;
WaveOut waveOut = new WaveOut();
waveOut.Init(osc);
waveOut.Play();
Play MIDI
For the second case (play a string of MIDI commands) take again a look to another Charles Petzold article. His MidiStringPlayer
class offers everything you need (but you may need to strip out WPF code to use it where you want). Basic code to play MIDI with NAudio is:
using (MidiOut midiOut = new MidiOut(0))
{
midiOut.Send(MidiMessage.StartNote(60, 127, 0).RawData);
Thread.Sleep(1000);
midiOut.Send(MidiMessage.StopNote(60, 0, 0).RawData);
Thread.Sleep(1000);
}
If you really need to play notes from a string then you have to parse it, code is too long to post it here but in the link you'll find everything.
for NAudio solution looks like this
Test.Properties.Resources.aaa this is path of mp3
using (var ms = new MemoryStream(Test.Properties.Resources.aaa))
using (var rdr = new NAudio.Wave.Mp3FileReader(ms))
using (var wavStream = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(rdr))
using (var baStream = new NAudio.Wave.BlockAlignReductionStream(wavStream))
using (var waveOut = new NAudio.Wave.WaveOut(NAudio.Wave.WaveCallbackInfo.FunctionCallback())) {
waveOut.Init(baStream);
waveOut.Play();
while (waveOut.PlaybackState == NAudio.Wave.PlaybackState.Playing) {
System.Threading.Thread.Sleep(100);
}
}
You can embed any kind of file into your project by adding it to your resource.
In Visual Studio you can do that by Resources --> Add Resource --> Add existing file.
In my case I named the resource file mySound.
Then you can open the file by adding a SoundPlayer
which takes the resource as parameter.
e.g.
SoundPlayer mysoundplayer = new SoundPlayer(MyAssemblyName.Properties.Resources.mySound);
mysoundplayer.Play();