'How to play sound from .sf2 files in C#?
I'm trying to code a music composer app for my final year project in C# and I can't find any APIs or relevant code that can help me play sound from .sf2 files.
The closest thing I can find is MeltySynth. However, the author didn't provide much documentation for this API, so it is really hard for me to understand the commands in it. I've only managed to get this API to play midi files, not play the relevant notes from the .sf2 file I want. There is a section in the GitHub page that shows users how to use the API to play melody with notes in the soundfont file:
// Create the synthesizer.
var sampleRate = 44100;
var synthesizer = new Synthesizer("TimGM6mb.sf2", sampleRate);
// The length of a block is 0.1 sec.
var blockSize = sampleRate / 10;
// The entire output is 3 sec.
var blockCount = 30;
// Define the melody.
// A single row indicates the start timing, end timing, and pitch.
var data = new int[][]
{
new int[] { 5, 10, 60 },
new int[] { 10, 15, 64 },
new int[] { 15, 25, 67 }
};
// The output buffer.
var left = new float[blockSize * blockCount];
var right = new float[blockSize * blockCount];
for (var t = 0; t < blockCount; t++)
{
// Process the melody.
foreach (var row in data)
{
if (t == row[0]) synthesizer.NoteOn(0, row[2], 100);
if (t == row[1]) synthesizer.NoteOff(0, row[2]);
}
// Render the block.
var blockLeft = left.AsSpan(blockSize * t, blockSize);
var blockRight = right.AsSpan(blockSize * t, blockSize);
synthesizer.Render(blockLeft, blockRight);
}
I copied the code exactly and tried running it in a simple C# CLI class program (and making the necessary changes like the .sf2 file directory of course) and it does not work, I have no clue on how to troubleshoot this problem, the program ran and exited just fine. There weren't any error messages or any exceptions thrown, I just don't hear any sound.
The sample code given by the author here ran perfectly on my computer and managed to play the specified midi file with the given .sf2 files' sounds, therefore I doubt there was any compatibility issues with my audio driver and hardware.
I'd appreciate it if someone has an alternate idea on how I can access the sound files inside of .sf2 files or a clear understanding on how to use MeltySynth.
Solution 1:[1]
I created a MidiSampleProvider like in the working MidiPlayer sample for the synthesizer:
using System;
using NAudio.Wave;
using MeltySynth;
namespace Test
{
public class MidiSampleProvider : ISampleProvider
{
private static WaveFormat format = WaveFormat.CreateIeeeFloatWaveFormat(44100, 2);
private Synthesizer _synthesizer;
public MidiSampleProvider(Synthesizer synthesizer)
{
_synthesizer = synthesizer;
}
public int Read(float[] buffer, int offset, int count)
{
_synthesizer.RenderInterleaved(buffer.AsSpan(offset, count));
return count;
}
public WaveFormat WaveFormat => format;
}
}
In order to play a chord I used WaveOut of NAudio:
using MeltySynth;
using NAudio.Wave;
....
var synthesizer = new Synthesizer("TimGM6mb.sf2", sampleRate);
MidiSampleProvider provider = new MidiSampleProvider(synthesizer);
var waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());
waveOut.Init(provider);
waveOut.Play();
synthesizer.NoteOn(0, 60, 100);
synthesizer.NoteOn(0, 64, 100);
synthesizer.NoteOn(0, 67, 100);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | koan |
