public void BasicOperations() { using (var buf = new RingBuffer()) { Assert.Equal(0, buf.BytesAvailable()); Assert.Equal(8191, buf.WriteBytesAvailable()); // implementation dependent. using (var synth = new SynthUnit(buf)) { var bytes = new byte [] { 0x90, 0x30, 0 }; // note on at 0x30, but with no velocity = no sound. buf.Write(bytes, 0, bytes.Length); var results = new short [1024]; Assert.Equal(3, buf.BytesAvailable()); synth.Init(44100); synth.GetSamples(results, 0, results.Length); Assert.All(results, r => Assert.Equal(0, r)); bytes = new byte [] { 0x90, 0x30, 100 }; // now give vel = 100 buf.Write(bytes, 0, bytes.Length); synth.GetSamples(results, 0, results.Length); Assert.Contains(results, r => r != 0); // to see what's being generated, enable these lines. //var str = string.Concat (results.Select (s => s.ToString ("X04"))); //Console.WriteLine (str); } } }
void WriteCallback(SoundIOOutStream outStream, int min, int max) { if (!play_audio) { return; } Console.WriteLine($"WriteCallback invoked: {min} / {max}"); double float_sample_rate = outStream.SampleRate; double seconds_per_frame = 1.0 / float_sample_rate; //if (max - min > samples.Length) // samples = new short [max - min]; #if test_with_sine //double seconds_offset = 0; #else synth.GetSamples(samples, 0, samples.Length); #endif //if (samples.Any (s => s != 0)) // Console.WriteLine (string.Concat (samples.Take (50).Select (s => s.ToString ("X04")))); int frameRemaining = max; int frameCount = frameRemaining; while (play_audio && frameRemaining > 0) { var results = outStream.BeginWrite(ref frameCount); if (frameCount == 0) { break; } #if test_with_sine double pitch = 440.0; double radians_per_second = pitch * 2.0 * Math.PI; for (int frame = 0; frame < frameCount; frame += 1) { double sample = Math.Sin((seconds_offset + frame * seconds_per_frame) * radians_per_second); for (int channel = 0; channel < outStream.Layout.ChannelCount; channel += 1) { var area = results.GetArea(channel); double range = (double)short.MaxValue - (double)short.MinValue; double val = sample * range / 2.0; unsafe { *((short *)area.Pointer) = (short)val; } area.Pointer += area.Step; } } seconds_offset = Math.IEEERemainder(seconds_offset + seconds_per_frame * frameCount, 1.0); #else for (int i = 0; i < outStream.Layout.ChannelCount; i++) { var area = results.GetArea(i); unsafe { Marshal.Copy(samples, 0, area.Pointer, samples.Length); area.Pointer += area.Step * samples.Length; } } #endif outStream.EndWrite(); frameRemaining -= frameCount; } }