英文:
Calculate the level/amplitude/db of audio for two channels
问题
我已阅读有关从AudioInputStream中提取样本并将其转换为分贝的两篇帖子。在第一篇文章中,它展示了如何从一个通道(单声道)获取样本。因此,我的问题是,我想要单独获取左声道和右声道的样本,以便计算左声道和右声道的分贝。
以下是代码部分,可以如何更改以单独获取左声道和右声道?
final byte[] buffer = new byte[2048];
float[] leftChannelSamples = new float[buffer.length / 4]; // Samples for left channel
float[] rightChannelSamples = new float[buffer.length / 4]; // Samples for right channel
for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
line.write(buffer, 0, n);
for (int i = 0, leftIndex = 0, rightIndex = 1; i < n; ) {
int leftSample = 0;
int rightSample = 0;
leftSample |= buffer[i++] & 0xFF; // (reverse these two lines
leftSample |= buffer[i++] << 8; // if the format is big endian)
rightSample |= buffer[i++] & 0xFF; // (reverse these two lines
rightSample |= buffer[i++] << 8; // if the format is big endian)
// normalize to range of +/-1.0f
leftChannelSamples[leftIndex++] = leftSample / 32768f;
rightChannelSamples[rightIndex++] = rightSample / 32768f;
}
float leftRms = 0f;
float rightRms = 0f;
for (float leftSample : leftChannelSamples) {
leftRms += leftSample * leftSample;
}
for (float rightSample : rightChannelSamples) {
rightRms += rightSample * rightSample;
}
leftRms = (float) Math.sqrt(leftRms / leftChannelSamples.length);
rightRms = (float) Math.sqrt(rightRms / rightChannelSamples.length);
// Calculate dB for left and right channels using leftRms and rightRms
}
希望这能帮助到您。提前感谢您的帮助。
英文:
I have read two posts about extracting samples from AudioInputStream and converting them in to dB.
https://stackoverflow.com/a/26576548/8428414
https://stackoverflow.com/a/26824664/8428414
As far as I understand byte[] bytes;
has structure like this:
Index 0: Sample 0 (Left Channel)
Index 1: Sample 0 (Right Channel)
Index 2: Sample 1 (Left Channel)
Index 3: Sample 1 (Right Channel)
Index 4: Sample 2 (Left Channel)
Index 5: Sample 2 (Right Channel)
In the first article it shows how to get samples from one channel (mono).
So, my problem is that I want to get samples separately for the right channel and separately for the left channel in order to calculate dB for right and left channels.
Here is the code. How it can be changed to get right and left channels separately?
I can't understand how the index i
changes...
final byte[] buffer = new byte[2048];
float[] samples = new float[buffer.length / 2];
for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
line.write(buffer, 0, n);
for (int i = 0, sampleIndex = 0; i < n; ) {
int sample = 0;
sample |= buffer[i++] & 0xFF; // (reverse these two lines
sample |= buffer[i++] << 8; // if the format is big endian)
// normalize to range of +/-1.0f
samples[sampleIndex++] = sample / 32768f;
}
float rms = 0f;
for (float sample : samples) {
rms += sample * sample;
}
rms = (float) Math.sqrt(rms / samples.length);
Hope you could help me. Thank you in advance.
答案1
得分: 4
立体声信号保存的格式被称为交错格式。也就是说,正如您正确描述的那样,它是LLRRLLRRLLRR...
。因此,您首先需要读取左声道样本,然后是右声道样本,依此类推。
我已经根据这一点编辑了您的代码。然而,通过重构,还有一些改进的空间。
注意: 代码更改仅涉及交错。我没有检查您代码的其余部分。
final byte[] buffer = new byte[2048];
// 创建两个缓冲区。一个用于左声道,一个用于右声道。
float[] leftSamples = new float[buffer.length / 4];
float[] rightSamples = new float[buffer.length / 4];
for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
line.write(buffer, 0, n);
for (int i = 0, sampleIndex = 0; i < n; ) {
int leftSample = 0;
int rightSample = 0;
leftSample |= buffer[i++] & 0xFF; // (如果格式是大端,请颠倒这两行)
leftSample |= buffer[i++] << 8;
rightSample |= buffer[i++] & 0xFF; // (如果格式是大端,请颠倒这两行)
rightSample |= buffer[i++] << 8;
// 归一化到范围+/-1.0f
leftSamples[sampleIndex] = leftSample / 32768f;
rightSamples[sampleIndex] = rightSample / 32768f;
sampleIndex++;
}
// 现在计算左声道的均方根(RMS)
float leftRMS = 0f;
for (float sample : leftSamples) {
leftRMS += sample * sample;
}
leftRMS = (float) Math.sqrt(leftRMS / leftSamples.length);
// ...以及右声道
float rightRMS = 0f;
for (float sample : rightSamples) {
rightRMS += sample * sample;
}
rightRMS = (float) Math.sqrt(rightRMS / rightSamples.length);
}
英文:
The format the stereo signal is saved in is called interleaved. I.e., as you described correctly, it's LLRRLLRRLLRR...
. SO you first need to read a left sample, then a right sample, and so on.
I have edited your code to reflect this. However, there is some room for improvement via refactoring.
Note: The code changes only deal with interleaving. I have not checked the rest of your code.
final byte[] buffer = new byte[2048];
// create two buffers. One for the left, one for the right channel.
float[] leftSamples = new float[buffer.length / 4];
float[] rightSamples = new float[buffer.length / 4];
for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
line.write(buffer, 0, n);
for (int i = 0, sampleIndex = 0; i < n; ) {
int sample = 0;
leftSample |= buffer[i++] & 0xFF; // (reverse these two lines
leftSample |= buffer[i++] << 8; // if the format is big endian)
rightSample |= buffer[i++] & 0xFF; // (reverse these two lines
rightSample |= buffer[i++] << 8; // if the format is big endian)
// normalize to range of +/-1.0f
leftSamples[sampleIndex] = leftSample / 32768f;
rightSamples[sampleIndex] = rightSample / 32768f;
sampleIndex++;
}
// now compute RMS for left
float leftRMS = 0f;
for (float sample : leftSamples) {
leftRMS += sample * sample;
}
leftRMS = (float) Math.sqrt(leftRMS / leftSamples.length);
// ...and right
float rightRMS = 0f;
for (float sample : rightSamples) {
rightRMS += sample * sample;
}
rightRMS = (float) Math.sqrt(rightRMS / rightSamples.length);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论