Skip to content
Advertisement

SourceDataLine doubling framerate

From my research, I cannot seem to find anyone else with the same problem which leads me to believe I’m just committing an unholy amount of stupidity. Nonetheless, I’m working with the Java sampled sound API and I’m trying to play a simple 440Hz sine wave for 5 seconds. However, it seems as though the SourceDataLine is eating through the frames at twice the speed of its given AudioFormat framerate. The sample I’m using is:

AudioFormat audioFormat = new AudioFormat(
    AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 22050, false);
SourceDataLine outLine;

int bufferByteLength = 4096;
byte[] b = new byte[4];
final float framePeriod = 1.0f / audioFormat.getFrameRate();
int frame = 0;

outLine = AudioSystem.getSourceDataLine(audioFormat);
outLine.open(audioFormat, bufferByteLength);
outLine.start();

System.out.println("Format: " + audioFormat);

double begin = System.nanoTime();
while((frame * framePeriod) < 5){
    short sample = (short)(0.2 * Math.sin(2 * Math.PI * 440 * frame * framePeriod) * Short.MAX_VALUE);
    b[0] = (byte)(sample & 0xFF);
    b[1] = (byte)((sample >> 8) & 0xFF);
    b[2] = (byte)(sample & 0xFF);
    b[3] = (byte)((sample >> 8) & 0xFF);
    ++frame;
    outLine.write(b, 0, 4);
}
double end = System.nanoTime();

System.out.println("True elapsed (seconds): " + (end - begin) * 1e-9);
System.out.println("Line reported elapsed (seconds): " + outLine.getMicrosecondPosition() * 1e-6);

outLine.drain();
outLine.stop();
outLine.close();

which, on my machine, prints out

Format: PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, 22050.0 frames/second, little-endian
True elapsed (seconds): 2.5011672000000003
Line reported elapsed (seconds): 4.901496

so as expected from the 880Hz pitch, the line is indeed going through the frames twice as fast. I find this particularly odd because I’m clearly writing 4 bytes that it requires for a single frame, yet it appears to require 8? In fact, when I use a b size of 8 (and by extension write 8 bytes), indeed it brings the pitch down to 440Hz and oddly does not induce any “pops” even though the latter 4 bytes in b are always 0.

An interesting thing I’ve noticed is that the line requires a buffer size of 1764 or higher, otherwise it will stutter quite dramatically and bring the effective framerate down significantly below the expected 22050. Though, I expect this to be more CPU dependent than anything.

I’m quite puzzled. I do not know what may be causing this, so I am hoping someone out there has had this problem before, or can offer any clues as to why this is happening. Cheers.

Advertisement

Answer

You are specifying a sample rate of twice the frame rate so it is expecting twice as many samples. These two rates are usually the same for PCM.

The sample rate is per channel not the total for all channels.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement