C 我从SDL回拨音频的时间报告遵循这种奇怪的模式,这有什么原因吗?
我有一个使用SDL2生成两个saw波的基本示例。它似乎工作得很好,因为它听起来就像我期望的那样。然而,当我打印回调之间的时间间隔时,间隔远远不是我期望的偶数间隔。这有什么原因吗 以下是显示一些格式数据和几十个间隔的输出:C 我从SDL回拨音频的时间报告遵循这种奇怪的模式,这有什么原因吗?,c,linux,audio,sdl,C,Linux,Audio,Sdl,我有一个使用SDL2生成两个saw波的基本示例。它似乎工作得很好,因为它听起来就像我期望的那样。然而,当我打印回调之间的时间间隔时,间隔远远不是我期望的偶数间隔。这有什么原因吗 以下是显示一些格式数据和几十个间隔的输出: want: freq : 48000 format : 33056 channels: 2 silence : 0 samples : 1024 size : 0 have: freq : 48000 format
want:
freq : 48000
format : 33056
channels: 2
silence : 0
samples : 1024
size : 0
have:
freq : 48000
format : 33056
channels: 2
silence : 0
samples : 512
size : 4096
41
0
0
12
6
18
17
0
18
12
0
17
18
0
17
12
0
18
17
0
17
12
1
17
17
1
12
17
0
17
19
0
12
17
0
18
17
1
11
18
0
17
12
0
18
18
0
17
12
0
17
18
0
17
12
0
18
17
0
6
18
17
0
12
17
1
17
17
1
11
18
0
17
7
17
17
1
11
18
0
17
12
0
18
17
0
17
12
0
19
12
0
16
18
0
18
12
0
etc...
代码如下:
/*
* compiled with:
* gcc -Wall twosaw.c -o twosaw `sdl2-config --cflags --libs`
*/
#include <stdio.h>
#include "SDL.h"
#define AudSamRat 48000
#define AudBufLen 1024
Uint32 lastTime;
Uint32 thisTime;
float phaseL = -1;
float phaseR = -1;
void fillAudioBuffer(void *unused, Uint8 *byteStream, int byteStreamLength)
{
//printf("byteStreamLength: %d\n", byteStreamLength); //-> 4096
float* floatStream = (float*) byteStream;
Uint32 floatStreamLength = byteStreamLength/4; //-> 1024
thisTime=SDL_GetTicks();
printf("%2d\n", thisTime-lastTime);
lastTime =thisTime;
int i;
for (i = 0; i<floatStreamLength; i+=2)
{
floatStream[i] = phaseL; //left
floatStream[i+1] = phaseR; //right
phaseL += 0.01;
phaseR += 0.02;
if (phaseL > 1) phaseL = -1;
if (phaseR > 1) phaseR = -1;
}
}
void logSpec(SDL_AudioSpec *as)
{
printf(
" freq : %5d\n"
" format : %5d\n"
" channels: %5d\n"
" silence : %5d\n"
" samples : %5d\n"
" size : %5d\n\n",
(int) as->freq,
(int) as->format,
(int) as->channels,
(int) as->silence,
(int) as->samples,
(int) as->size
);
}
int main(void)
{
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
SDL_AudioSpec want, have;
SDL_AudioDeviceID AudDev;
SDL_zero(want);
want.freq = AudSamRat;
want.format = AUDIO_F32;
want.channels = 2;
want.samples = AudBufLen;
want.callback = fillAudioBuffer;
AudDev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (AudDev == 0) {
printf("Failed to open audio: %s\n", SDL_GetError());
return 1;
} else {
printf("\nwant:\n");
logSpec(&want);
printf("have:\n");
logSpec(&have);
if (have.format != want.format) // we let this one thing change.
printf("We didn't get Float32 audio format.\n");
SDL_PauseAudioDevice(AudDev, 0); // start audio playing.
SDL_Delay(3000); // let the audio callback play some sound for 3 seconds.
SDL_CloseAudioDevice(AudDev);
}
SDL_Quit();
return 0;
}
/*
*汇编时使用:
*gcc-Wall twosaw.c-o twosaw`sdl2 config--cflags--libs`
*/
#包括
#包括“SDL.h”
#定义AudSamRat 48000
#定义AudBufLen 1024
上次Uint32;
这次是Uint32;
浮动相位=-1;
浮相器=-1;
void fillAudioBuffer(void*未使用、Uint8*字节流、int字节流长度)
{
//printf(“byteStreamLength:%d\n”,byteStreamLength);//->4096
float*floatStream=(float*)byteStream;
Uint32 floatStreamLength=ByTestStreamLength/4;//->1024
thisttime=SDL_GetTicks();
printf(“%2d\n”,这次是上次);
上次=这次;
int i;
对于(i=0;i 1)相位=-1;
如果(相位器>1)相位器=-1;
}
}
无效日志规范(SDL_AudioSpec*as)
{
printf(
“频率:%5d\n”
“格式:%5d\n”
“频道:%5d\n”
“静默:%5d\n”
“样本:%5d\n”
“大小:%5d\n\n”,
(int)as->freq,
(int)as->format,
(int)as->channels,
(int)as->silence,
(int)as->samples,
(int)as->size
);
}
内部主(空)
{
SDL_Init(SDL_Init_音频| SDL_Init_计时器);
SDL_AudioSpec想要,拥有;
SDL_AudioDeviceID AudDev;
SDL_零(需要);
want.freq=AudSamRat;
want.format=AUDIO_F32;
want.channels=2;
want.samples=AudBufLen;
want.callback=fillAudioBuffer;
AudDev=SDL\u OpenAudioDevice(NULL、0、&want、&have、SDL\u AUDIO\u ALLOW\u FORMAT\u CHANGE);
如果(AudDev==0){
printf(“无法打开音频:%s\n”,SDL_GetError());
返回1;
}否则{
printf(“\n地址:\n”);
logSpec(&want);
printf(“have:\n”);
日志规范(&have);
如果(have.format!=want.format)//我们让这一点改变。
printf(“我们没有得到Float32音频格式。\n”);
SDL_PauseAudioDevice(AudDev,0);//开始音频播放。
SDL_Delay(3000);//让音频回调播放一些声音3秒钟。
SDL_闭合音频设备(AudDev);
}
SDL_退出();
返回0;
}
SDL\u GetTicks(),用于计时,在Windows的引擎盖下调用GetTickCount()。GetTickCount()的粒度大约为10-25ms(取决于您询问的对象),这意味着它对这个应用程序或多或少是无用的
不过,我确实想知道,通过查看回调何时被调用,您试图确定什么?如果您确实需要了解,请查看windows下的QueryPerformanceCounter API。或者,如果您有幸使用现代编译器,请使用std::chrono
正在使用QueryPerformanceCounter
// only need to do this part once
LARGE_INTEGER Freq;
QueryPerformanceFrequency(&Freq);
// Then, for timing
LARGE_INTEGER Time;
QueryPerformanceCounter(&Time);
double TimeInSeconds = double(Time.QuadPart) / double(Freq.QuadPart);
使用std::chrono
// at the start. chrono uses intervals, and wants a start time (I think)
auto StartTime = std::chrono::high_resolution_clock::now();
// during
std::chrono::duration<double> fsec = std::chrono::high_resolution_clock::now() - StartTime;
double TimeInSecondsSinceStart = fsec.count();
//开始时。chrono使用间隔,并且想要一个开始时间(我想)
自动启动时间=标准::时钟::高分辨率时钟::现在();
//期间
std::chrono::duration fsec=std::chrono::high_resolution_clock::now()-StartTime;
double-timeUnsecondssinceStart=fsec.count();
或者您可以使用。非常好。另外,我认为我的回答在任何情况下都可能是错误的,因为稍微仔细阅读一下就会发现这个问题几乎肯定是关于Linux机器的。