meltysynth icon indicating copy to clipboard operation
meltysynth copied to clipboard

Provide example showing how to play notes with NAudio

Open jeffoulet opened this issue 1 year ago • 10 comments

Hi,

Sorry, my request might sound like a very stupid one, and maybe this is not the correct place to ask, but I'm struggling to actually play the waveform generated by Meltysynth.

What I'm trying to do:

  • generate a midi file in memory
  • render it with Meltysynth into a memory stream
  • finally play the stream

What I've achieved so far:

private static void PlayMeltysynthChord()
		{
			var sampleRate = 44100;
			var synthesizer = new Synthesizer(@"..\Resources\Raw\Abbey-Steinway-D-v1.9.sf2", sampleRate);

			synthesizer.NoteOn(0, 60, 100);
			synthesizer.NoteOn(0, 63, 100);
			synthesizer.NoteOn(0, 66, 100);

			var mono = new float[3 * sampleRate];
			synthesizer.RenderMono(mono);

			var byteArray = new byte[mono.Length * 4];
			Buffer.BlockCopy(mono, 0, byteArray, 0, byteArray.Length); 

			var wav = new WavePcmFormat(byteArray, numChannels: 1, sampleRate: (uint)sampleRate, bitsPerSample: 16);
			var rawDataWithHeader = wav.ToBytesArray();

			var stream = new MemoryStream(rawDataWithHeader);

			var player = new System.Media.SoundPlayer(stream);
			player.Play();
		}

The 'WavePCMFormat' method inserts the .wav header to the data. The result I get is a few seconds of white noise, so I assume there is something wrong in the transformation of the rendered PCM to the .wav stream.

Any help is welcome... Thanks in advance

jeffoulet avatar Feb 08 '23 21:02 jeffoulet

You are rendering the waveform to a float array. Since float is 32bit, it's not compatible with bitsPerSample: 16. You should use RenderMonoInt16 and a short array.

By the way, if you want to play a MIDI file, I strongly recommend to use NAudio.Wave.WaveOut or another callback based playback. A fire-and-forget playback like System.Media.SoundPlayer is not suitable for playing a long MIDI file, because it needs a lot of memory to store the whole waveform.

Isn't the existing NAudio example suitable for your application? Is there a special reason to use System.Media.SoundPlayer? If you could be a bit more specific about what you want to do, I might be able to help 🙂

sinshu avatar Feb 09 '23 09:02 sinshu

You are rendering the waveform to a float array. Since float is 32bit, it's not compatible with bitsPerSample: 16. You should use RenderMonoInt16 and a short array.

By the way, if you want to play a MIDI file, I strongly recommend to use NAudio.Wave.WaveOut or another callback based playback. A fire-and-forget playback like System.Media.SoundPlayer is not suitable for playing a long MIDI file, because it needs a lot of memory to store the whole waveform.

Isn't the existing NAudio example suitable for your application? Is there a special reason to use System.Media.SoundPlayer? If you could be a bit more specific about what you want to do, I might be able to help 🙂

Hello Sinshu,

Since WaveOut is only available for PC, can you recommend a similar approach for Mac?

Thanks!

rjjaret avatar Aug 11 '23 23:08 rjjaret

@rjjaret If you want to play MIDI files, please try one of the following examples. https://github.com/sinshu/meltysynth#examples

For instance, SFML.Net supports Mac, so I believe it should function on a Mac as well.

sinshu avatar Aug 12 '23 01:08 sinshu

I want to play a stream, similar to what is being done in the Windows example above. They're originally using System.Media.SoundPlayer, and you suggested WaveOut. But WaveOut is only for PC.

I haven't seen anything quite like that for Mac in the examples, but I'll give another look. Please suggest a place if you know of one.

Alternatively, if there's a way to play a series of midi notes, without saving to file first, that would achieve what I need too.

Thanks! Rob

rjjaret avatar Aug 14 '23 20:08 rjjaret

@rjjaret Did you try the SFML.Net example?

sinshu avatar Aug 14 '23 21:08 sinshu

I have just made a demo showing how to play notes triggered from a MIDI keyboard with NAudio and MeltySynth which I plan to show at my talk about NAudio at the Copenhagen Developer Festival next week. It's the first time I've tried MeltySynth and I have to say it's amazing! Brilliant job, and I was very impressed at how easy it was to integrate with NAudio.

I'll post an example on my blog hopefully in the next week and I'll try to remember to link to it here as well.

markheath avatar Aug 23 '23 20:08 markheath

@markheath Very nice! I'm looking forward to the blog post 😎

sinshu avatar Aug 23 '23 23:08 sinshu

Blog post is up: https://markheath.net/post/naudio-midi-playback-soundfont-meltysynth Will try to get the sample project onto GitHub as well soon

markheath avatar Aug 31 '23 16:08 markheath

@markheath Thank you for sharing information 👍

sinshu avatar Sep 01 '23 00:09 sinshu

@jeffoulet You can look at my provided code sample for playback MIDI using NAudio below. It's minimalist and fully functional (but consumes lots of memory).

https://github.com/sinshu/meltysynth/issues/41#issuecomment-1761533356

chaojian-zhang avatar Oct 13 '23 13:10 chaojian-zhang