C-有原因是我从SDL Kinda中报告的音频回调的时机遵循了这种怪异的模式



我有一个非常基本的示例,即使用sdl2生成两个锯。它似乎正常工作,因为它听起来像我期望的那样。但是,当我在回调之间打印时间时,间隔远非我期望的偶数间隔。有这样的原因吗?

这是显示一些格式数据的输出,然后几十个间隔:

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: %dn", byteStreamLength); //-> 4096
  float* floatStream = (float*) byteStream;
  Uint32 floatStreamLength = byteStreamLength/4; //-> 1024
  thisTime=SDL_GetTicks();
  printf("%2dn", 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    : %5dn"
    " format  : %5dn"
    " channels: %5dn"
    " silence : %5dn"
    " samples : %5dn"
    " size    : %5dnn",
    (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: %sn", 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;
}

sdl_getticks(),您用于定时,请在窗户的引擎盖下调用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();

最新更新