SDL 音频音调 - 播放速率
SDL Audio Pitch - Playback Rate
我的目标是将发动机的转速与声音的音调联系起来。我使用 SDL 作为我的音频后端。
所以我的想法是比正常情况更快地从波缓冲区中采样。因此,通过反复试验,我现在可以调整引擎声音 "step by step"。
问题 #1
如果我将这部分更改为:
audioBuff += 1 + pitch * 2;
到
audioBuff += 2
我只听到噪音。为什么?这与立体声通道有关吗?
问题 #2
我怎样才能使它成为线性间距?目前是 "stepping" 球场。
完整代码如下:
#include "SDL2/SDL.h"
#include <iostream>
void audioCallback(void* userdata, Uint8 *stream, int len);
Uint8 *audioBuff = nullptr;
Uint8 *audioBuffEnd = nullptr;
Uint32 audioLen = 0;
bool quit = false;
Uint16 pitch = 0;
int main()
{
if(SDL_Init(SDL_INIT_AUDIO) < 0)
return -1;
Uint32 wavLen = 0;
Uint8 *wavBuff = nullptr;
SDL_AudioSpec wavSpec;
if(SDL_LoadWAV("test.wav", &wavSpec, &wavBuff, &wavLen) == nullptr)
{
return 1;
}
wavSpec.callback = audioCallback;
wavSpec.userdata = nullptr;
wavSpec.format = AUDIO_S16;
wavSpec.samples = 2048;
audioBuff = wavBuff;
audioBuffEnd = &wavBuff[wavLen];
audioLen = wavLen;
if( SDL_OpenAudio(&wavSpec, NULL) < 0)
{
fprintf(stderr, "Could not open audio: %s\n", SDL_GetError());
return 1;
}
SDL_PauseAudio(0);
while(!quit)
{
SDL_Delay(500);
pitch ++;
}
SDL_CloseAudio();
SDL_FreeWAV(wavBuff);
return 0;
}
Uint32 sampleIndex = 0;
void audioCallback(void* userdata, Uint8 *stream, int len)
{
Uint32 length = (Uint32)len;
length = (length > audioLen ? audioLen : length);
for(Uint32 i = 0; i < length; i++)
{
if(audioBuff > audioBuffEnd)
{
quit = true;
return;
}
// why pitch * 2?
// how to get a smooth pitch?
stream[i] = audioBuff[0];
audioBuff += 1 + pitch * 2;
fprintf(stdout, "pitch: %u\n", pitch);
}
}
您正在将音频格式设置为 AUDIO_S16
,即 "Signed 16-bit little-endian samples"。每个样本都是两个字节,第一个字节是 LSB。当您读取 audioCallback
中的数据时,您是将其作为字节(8 位)读取,然后将这些字节传递回预期为 16 位的内容。因此,您会收到噪音,当您使用 audioBuff +=2;
时,您总是在读取音频样本的 LSB,当以这种方式使用时,它本质上是噪音。
您应该始终使用 16 位或 8 位样本。
我的目标是将发动机的转速与声音的音调联系起来。我使用 SDL 作为我的音频后端。
所以我的想法是比正常情况更快地从波缓冲区中采样。因此,通过反复试验,我现在可以调整引擎声音 "step by step"。
问题 #1
如果我将这部分更改为:
audioBuff += 1 + pitch * 2;
到
audioBuff += 2
我只听到噪音。为什么?这与立体声通道有关吗?
问题 #2
我怎样才能使它成为线性间距?目前是 "stepping" 球场。
完整代码如下:
#include "SDL2/SDL.h"
#include <iostream>
void audioCallback(void* userdata, Uint8 *stream, int len);
Uint8 *audioBuff = nullptr;
Uint8 *audioBuffEnd = nullptr;
Uint32 audioLen = 0;
bool quit = false;
Uint16 pitch = 0;
int main()
{
if(SDL_Init(SDL_INIT_AUDIO) < 0)
return -1;
Uint32 wavLen = 0;
Uint8 *wavBuff = nullptr;
SDL_AudioSpec wavSpec;
if(SDL_LoadWAV("test.wav", &wavSpec, &wavBuff, &wavLen) == nullptr)
{
return 1;
}
wavSpec.callback = audioCallback;
wavSpec.userdata = nullptr;
wavSpec.format = AUDIO_S16;
wavSpec.samples = 2048;
audioBuff = wavBuff;
audioBuffEnd = &wavBuff[wavLen];
audioLen = wavLen;
if( SDL_OpenAudio(&wavSpec, NULL) < 0)
{
fprintf(stderr, "Could not open audio: %s\n", SDL_GetError());
return 1;
}
SDL_PauseAudio(0);
while(!quit)
{
SDL_Delay(500);
pitch ++;
}
SDL_CloseAudio();
SDL_FreeWAV(wavBuff);
return 0;
}
Uint32 sampleIndex = 0;
void audioCallback(void* userdata, Uint8 *stream, int len)
{
Uint32 length = (Uint32)len;
length = (length > audioLen ? audioLen : length);
for(Uint32 i = 0; i < length; i++)
{
if(audioBuff > audioBuffEnd)
{
quit = true;
return;
}
// why pitch * 2?
// how to get a smooth pitch?
stream[i] = audioBuff[0];
audioBuff += 1 + pitch * 2;
fprintf(stdout, "pitch: %u\n", pitch);
}
}
您正在将音频格式设置为 AUDIO_S16
,即 "Signed 16-bit little-endian samples"。每个样本都是两个字节,第一个字节是 LSB。当您读取 audioCallback
中的数据时,您是将其作为字节(8 位)读取,然后将这些字节传递回预期为 16 位的内容。因此,您会收到噪音,当您使用 audioBuff +=2;
时,您总是在读取音频样本的 LSB,当以这种方式使用时,它本质上是噪音。
您应该始终使用 16 位或 8 位样本。