-1

I'm wondering if there is a way to adapt the code shown here so that I can basically make an array of beeps and play them all at once.

I tried making global MemoryStream and BinaryWriter to use, calculating everything ahead of time for the size but it was even slower than 1 beep at a time and didn't seem to work.

After that, I tried writing the MemoryStream to a byte array but that did the same as making globals for the stream/writer.

How can I edit the code to get the MemoryStream to hold multiple beeps and play them all at once?

JDoe
  • 19
  • 4
  • I think int sample in that code should be the combination / sum of `A[i] * Math.Sin(DeltaFT[i] * T))` for i = 0 .... (count-of-beeps-1). Maybe the sum of all A[i] would be the A in that code but I'm weak on music theory. – Dave S Dec 15 '17 at 23:42
  • Can you elaborate on what you mean by "array of beeps"? Are you trying to play a song (e.g. as in a MIDI file to wave file converter)? Or are you trying to combine multiple waveforms to make one note (e.g. as in a guitar pluck simulator)? – NetMage Dec 15 '17 at 23:52
  • @DaveS I'll try that and see how it goes. – JDoe Dec 15 '17 at 23:53
  • @NetMage I basically have a song made from different frequency/duration "beeps" but I don't want each beep to be its own mini wav but to combine them into 1 long .wav – JDoe Dec 15 '17 at 23:55
  • Using a global is the correct approach, but you must only put the header in once. – NetMage Dec 15 '17 at 23:56

1 Answers1

0

Here is a modification to create the song from beeps:

void Main() {
    var beeps = new[] {
        new Song.Beep(500, 1000, 200),
        new Song.Beep(1000, 1000, 300),
        new Song.Beep(300, 2000, 150),
        new Song.Beep(500, 500, 200),
    };

    var song = new Song(beeps);
    song.PlaySong();
}

public class Song {
    public struct Beep {
        readonly public int Amplitude;
        readonly public int Frequency;
        readonly public int Duration;

        public Beep(int a, int f, int d) {
            Amplitude = a;
            Frequency = f;
            Duration = d;
        }
    }

    MemoryStream MS;

    public Song(IEnumerable<Beep> beeps) {
        int Bytes = beeps.Sum(b => 4 * (441 * b.Duration / 10));

        int[] Hdr = { 0X46464952, 36 + Bytes, 0X45564157, 0X20746D66, 16, 0X20001, 44100, 176400, 0X100004, 0X61746164, Bytes };

        MS = new MemoryStream(44 + Bytes);
        using (var BW = new BinaryWriter(MS, Encoding.UTF8, true)) {
            for (int I = 0; I < Hdr.Length; ++I)
                BW.Write(Hdr[I]);

            foreach (var beep in beeps) {
                double A = ((beep.Amplitude * (System.Math.Pow(2, 15))) / 1000) - 1;
                double DeltaFT = 2 * Math.PI * beep.Frequency / 44100.0;

                int Samples = 441 * beep.Duration / 10;
                for (int T = 0; T < Samples; ++T) {
                    short Sample = System.Convert.ToInt16(A * Math.Sin(DeltaFT * T));
                    BW.Write(Sample); // left channel
                    BW.Write(Sample); // right channel
                }
            }
        }
    }

    public void PlaySong() {
        MS.Seek(0, SeekOrigin.Begin);
        using (var SP = new SoundPlayer(MS)) {
            SP.PlaySync();
        }
    }
}
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • Thanks NetMage, this worked to solve my problem! Do you happen to know why there are a few static bits in the middle? It's not big deal I was just curious. – JDoe Dec 16 '17 at 00:24
  • I changed my answer to create a song object that can be played multiple times. My guess would be that the code takes no pains to ensure the durations are rounding to the sample rate so that the waveforms terminate on 0, so there are sometimes discontinuities where the samples meet. You (I) could graph the samples to see that. – NetMage Dec 16 '17 at 00:32
  • I modified it so I could write the wave file and view it in my audio editor, and while it doesn't break the beep evenly, it isn't causing static for me either. Are you hearing static in my sample beep song? – NetMage Dec 16 '17 at 00:44
  • It doesn't seem to be happening with your song, only when I try doing a custom song, After a bit of testing it seems to happen when I use frequencies that don't divide nicely such as 262 or 294. – JDoe Dec 16 '17 at 00:55
  • I don't hear static but I do see a glitch in the waveform. Rounding to even cycles is proving tricky, however. – NetMage Dec 16 '17 at 01:24
  • Yeah, the song I'm playing is the happy birthday song, so I'm trying to see how it sounds if I play around with some frequencies and if I can do any rounding myself. – JDoe Dec 16 '17 at 01:31
  • Eric Lippert suggests another approach - sliding the next note to align better with the preceding notes duration here: https://stackoverflow.com/a/4974979/2557128 – NetMage Dec 18 '17 at 18:49
  • I actually saw that as I was looking further into it but in all honesty it I am struggling to follow along with a lot of his post. – JDoe Dec 18 '17 at 23:59