C 我从SDL回拨音频的时间报告遵循这种奇怪的模式,这有什么原因吗?

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

我有一个使用SDL2生成两个saw波的基本示例。它似乎工作得很好,因为它听起来就像我期望的那样。然而,当我打印回调之间的时间间隔时,间隔远远不是我期望的偶数间隔。这有什么原因吗

以下是显示一些格式数据和几十个间隔的输出:

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机器的。