我正在使用FMOD库从MP3中提取PCM。我得到了整个2通道--16位的东西,我还得到44100hz的采样率是1秒钟内的“声音”的44,100个样本。我没有得到的是,16位值究竟代表什么。我知道如何在xy轴上绘制坐标,但是我在绘制什么? y轴代表时间,x轴代表什么?声级?这与幅度相同吗?如何确定组成此值的不同声音。我的意思是,如何从16位数字中获取频谱。
这可能是一个单独的问题,但实际上我真正需要回答的问题是:如何在每25毫秒获得振幅?我是否取4400个值,除以40(40 * 0.025秒= 1秒)?得到1102.5个样本;那么我会将1102个值输入一个黑盒子,这个黑盒子能给我那个时刻的振幅吗?
编辑原始帖子添加我计划很快测试的代码:(注意,我将帧速率从25毫秒更改为40毫秒)
// 44100 / 25 frames = 1764 samples per frame -> 1764 * 2 channels * 2 bytes [16 bit sample] = 7056 bytes
private const int CHUNKSIZE = 7056;
uint bytesread = 0;
var squares = new double[CHUNKSIZE / 4];
const double scale = 1.0d / 32768.0d;
do
{
result = sound.readData(data, CHUNKSIZE, ref read);
Marshal.Copy(data, buffer, 0, CHUNKSIZE);
//PCM samples are 16 bit little endian
Array.Reverse(buffer);
for (var i = 0; i < buffer.Length; i += 4)
{
var avg = scale * (Math.Abs((double)BitConverter.ToInt16(buffer, i)) + Math.Abs((double)BitConverter.ToInt16(buffer, i + 2))) / 2.0d;
squares[i >> 2] = avg * avg;
}
var rmsAmplitude = ((int)(Math.Floor(Math.Sqrt(squares.Average()) * 32768.0d))).ToString("X2");
fs.Write(buffer, 0, (int) read);
bytesread += read;
statusBar.Text = "writing " + bytesread + " bytes of " + length + " to output.raw";
} while (result == FMOD.RESULT.OK && read == CHUNKSIZE);
加载mp3后,似乎我的rmsAmplitude在3C00到4900的范围内。我做错了吗?我期待更广泛的传播。
答案 0 :(得分:2)
答案 1 :(得分:0)
通常,x轴是时间值,y轴是幅度。要获得频率,您需要对数据进行傅里叶变换(最有可能使用快速傅立叶变换[fft]算法)。
要使用最简单的“声音”之一,我们假设你有一个频率为f的单一频率噪声。这表示(在幅度/时间域中)为y = sin(2 * pi * x / f)。 如果将其转换为频域,则最终只能使用Frequency = f。
答案 2 :(得分:0)
每个样本代表给定时间模拟信号的电压。