0

I'm trying to write a mini synth program. Essentially, every 200mS a timer is fired. When this is fired, 200mS worth of PCM samples are generated by the loop (e.g. sawtooth, sine wave etc, etc.), the number of samples related to the sample rate and scan period. e.g. every 200mS, 4000 samples are ready in the wave array for playing. My question is, how do I play this array i.e.what should the PlaySound method do? Invoking PlaySound every 200mS should play subsequent samples in a continuous manner. I have played around with DirectSound and NAudio to no avail.

    const int SAMPLE_RATE = 20000;
    const double SCAN_PERIOD = .2;  // S
    Timer _ScanTimer = new Timer();


    double[] wave = new double[(int)((double)SAMPLE_RATE * SCAN_PERIOD)];



 _ScanTimer.Tick += new EventHandler(_ScanTimer_Tick);




    private void _ScanTimer_Tick(object sender, EventArgs e) {
        int numSamplesPerTick = (int)((double)SAMPLE_RATE * SCAN_PERIOD);
        double secondsPerTick = (double)2 / SAMPLE_RATE;

        for (int i = 0; i < numSamplesPerTick; i++) {
            wave[i] = GetSynthOutput();
            _CurrentTime += secondsPerTick;
            if (_CurrentTime > double.MaxValue - 1)
                _CurrentTime = 0;

        }



        PlaySound(wave);
    }

I realise that the timer may not fire exactly every 200mS, and that the 4000 samples may contain slightly too few or too many samples for the actual time. I'm not worried about this as I can tweak the number of samples according to the actual time between subsequent timer firing.

afk5min
  • 1,856
  • 19
  • 32
  • Have you tried System.Media.SoundPlayer? Are your samples inside a stream? What is the exact sound format? – weismat Mar 06 '12 at 12:30
  • Currently they are in an array of doubles, one element per sample, but could be put into a memorrystream with no problem. Shall look at SoundPlayer in meantime. Cheers. – user1240122 Mar 06 '12 at 13:46

1 Answers1

1

Instead of creating sound on a timer, most audio synthesis programs work with two buffers - one is being filled while the other one is being played. NAudio allows you to do this by implementing the Read function in an ISampleProvider or IWaveProvider derived class. This method will be called whenever the soundcard wants more audio to play. You can set up your buffer sizes to be 200ms if you want.

Mark Heath
  • 45,254
  • 26
  • 128
  • 188