Search code examples
c#audiopcmgameboycscore

CScore output PCM bigger than one byte


I'm programming an C# emulator and decided to output the PCM using CScore. When the sample size (for each channel) is one byte, the sound outputs correctly, but when I increase the sample size to 16 bits, the sound is very very noisy.

A related question to that problem is how those 2 bytes are interpreted (are they signed? high byte first?)

This is roughly what I'm doing:

First I generate the samples as such

public void GenerateSamples(int sampleCount)
{
  while(sampleCount > 0)
  {
    --sampleCount;

    for(int c = 0; c < _numChannels; ++c)
    {
      _buffer[_sampleIndex++] = _outputValue;
    }

    // The amount of ticks in a sample
    _tickCounter -= APU.MinimumTickThreshold;
    if(_tickCounter < 0)
    {
      _tickCounter = _tickThreshold;
      _up = !_up;
      // Replicating signed behaviour
      _outputValue = (short)(_up ? 32767 : -32768);
    }
  }
}

This will generate a simple square wave with the frequency determined by the _tickThreshold. If the _buffer is a byte array, the sound is correct. I want to output it with shorts because it will enable me to use signed samples and simply add multiple channels in order to mix them.

This is how I'm outputting the sound.

  for(int i = 0; i < sampleCount; ++i)
  {
    for(int c = 0; c < _numChannels; ++c)
    {
      short sample = _channel.Buffer[_channelSampleIndex++];
      // Outputting the samples the other way around doesn't output
      // sound for me
      _buffer[_sampleIndex++] = (byte)sample;
      _buffer[_sampleIndex++] = (byte)(sample >> 8);
    }
  }

The WaveFormat I'm using is determined like this:

  _waveFormat = new WaveFormat(_apu.SampleRate,      // 44000
                               _apu.SampleSize * 8,  // 16
                               _apu.NumChannels);    // 2

I'm pretty sure there is something obvious I'm missing, but I've been debugging this for a while and don't seem to pinpoint where the problem is.

Thanks


Solution

  • Walk of shame here. The problem was that I wasn't taking in account that now I needed to generate half the amount of samples (CScore asked for amount of bytes, not samples). In my example, I had to divide the sampleCount variable by the sampleSize to generate the correct amount of sound.

    The noise came because I wasn't synchronizing the extra samples with the next Read call from CScore (I'm generating sound on the fly, instead of pre-buffering it. This way I have no delay introduced because of extra samples).

    I found out about the problem looking at this: SampleToPcm16.cs