Reputation: 6914
When calling AudioSystem.getLine(TargetDataLine.class, audioFormat), does the AudioFormat frameSize and frameRate have to rigidly specify a frame size equal to exactly one sample, and a frameRate equal to the sampleRate?
The following code works (in the sense of "compiles and runs without errors"), but seems to be horribly inefficient because it's seemingly bothering my code every time it captures literally one single 2-byte sample:
AudioFormat format= new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 48000, 16, 1, 2, 48000, true);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
...but if I try to make each frame 10x larger, and reduce the framerate by the same amount, AudioSystem.getLine() returns null:
// causes AudioSystem.getLine() to return null
AudioFormat lessFrequent = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 48000, 16, 1, 20, 4800, true);
... and to be honest, I really want it to buffer even longer frames, and only bother me every 100ms:
// pure fantasy:
AudioFormat ideal = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 48000, 16, 1, 9600, 10, true);
Am I doing something wrong, or is this happening because present-day computers (like a 2023 Macbook Pro) no longer have soundcards capable of capturing to their own ram & automatically DMA'ing it periodically without bothering the CPU every step of the way... so now, framerate and sample rate now have to be identical?
Assuming many/most -- but not all -- computers require that framerate and framesize have values corresponding to "exactly one sample", is there any way (using the Java API) for a program to discover whether the current computer falls into that category, or whether it's able to capture audio with larger & less-frequent frames? And if it can... either the range(s) or exact values that it regards as acceptable? Or, are you/the user literally expected to just keep blindly stabbing in the dark trying different permutations until one of them finally returns a non-null TargetDataLine?
Upvotes: 0
Views: 62
Reputation: 7910
A buffer size isn't part of the class AudioFormat
. But a buffer size can be specified for the SourceDataLine
or TargetDataLine
, the lines used for sending and receiving data, using the .open()
method.
I haven't played around with the different AudioFormat
constructors, have always just used this one:
public AudioFormat(AudioFormat.Encoding encoding,
float sampleRate,
int sampleSizeInBits,
int channels,
int frameSize,
float frameRate,
boolean bigEndian)
To keep things simple for myself, I stick with the standard "CD Quality" format:
encoding = AudioFormat.Encoding.PCM_SIGNED
sampleRate = 44100
sampleSizeInBits = 16
channels = 2 // stereo
frameSize = 4 // 2 bytes per sample x 2 channels
frameRate = 44100
bigEndian = false
I'm guessing that you have tools or external sources with audio data at 48000 fps.
In the API documentation for AudioFormat, there are a number of other constructors. There is one which doesn't require the size in bytes of a single frame. The API description for AudioFormat
also has definitions for all the variables & terms used.
Upvotes: 0