簡體   English   中英

將 SDL F32 字節轉換為樣本 [-1.0 - 1.0] 會導致靜態噪聲

[英]Converting SDL F32 Bytes to samples [-1.0 - 1.0] results in static noise

我正在嘗試將來自 SDL2 音頻設備的麥克風輸入轉換為浮點樣本。 目前我得到了靜態 -不是一致的靜態- 而是響應麥克風輸入的靜態。

因此,當麥克風不被通話時,不會聽到靜電聲。 當麥克風是時,靜態跟隨短語和動態變化。 我覺得我真的快要讓它工作了,但我做錯了(可能很明顯)。

我在 SDL 中設置音頻設備如下:

SDL_AudioSpec as;
as.freq = aSamplerate;
as.format = AUDIO_F32;
as.channels = 1;
as.samples = aBuffer;
as.callback = _sdl_cb;
as.userdata = (void*)aSoloud;
gAudioDeviceID = SDL_OpenAudioDevice(NULL, 1, &as, &gActiveAudioSpec, SDL_AUDIO_ALLOW_ANY_CHANGE & ~(SDL_AUDIO_ALLOW_FORMAT_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE));
if (gAudioDeviceID == 0)
{
    as.format = AUDIO_S16;
    gAudioDeviceID = SDL_OpenAudioDevice(NULL, 1, &as, &gActiveAudioSpec, SDL_AUDIO_ALLOW_ANY_CHANGE & ~(SDL_AUDIO_ALLOW_FORMAT_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE));
    if (gAudioDeviceID == 0)
    {
        return UNKNOWN_ERROR;
    }
}

//Calculate per sample bytes
int bytesPerSample = gActiveAudioSpec.channels * ( SDL_AUDIO_BITSIZE( gActiveAudioSpec.format ) / 8 );

gBufferByteSize = bytesPerSample * aBuffer;

audioHoldingPattern = new Uint8[ gBufferByteSize ];

memset( audioHoldingPattern, 0, gBufferByteSize );
SDL_PauseAudioDevice(gAudioDeviceID, 0);
  • gActiveAudioSpec 是從 SDL 返回的“正確”規范。
  • audioHoldingPattern 實際上是我的音頻緩沖區在回調中的保持模式(如下所示)。 我需要這樣的東西,因為我將它與一個請求緩沖區的庫(SoLoud)一起使用,而不是接受它們。 最新的緩沖區被保存在這里,直到它被發送回 SoLoud。

這就是我在 SDL 回調中所做的:

static void _sdl_cb(void * userdata, Uint8 * pcm, int len){
    if (SDL_GetAudioDeviceStatus(gAudioDeviceID) == SDL_AUDIO_PLAYING) {
        memcpy( &audioHoldingPattern[0], pcm, len );
    }
}

這就是 SoLoud 從以下位置請求新緩沖區的地方:

unsigned int MicrophoneInstance::getAudio(float* aBuffer, unsigned int aSamplesToRead, unsigned int aBufferSize)
{       
        int size = aBufferSize;
        float *signal = reinterpret_cast<float*>(audioHoldingPattern);

        memcpy(aBuffer, signal, aBufferSize);

        return (unsigned int)sizeof(signal);
}
  • aBuffer 是 SoLoud 提供的用於復制到的緩沖區

請幫忙!

您的帖子中沒有足夠的信息來幫助您。 當您設置 SDL 音頻上下文時,您已經指定了預期的音頻格式(可能是 16 位、小端、有符號)。 它可以是像 S16LE 或 U16LE 或...

一旦您在代碼中發現了這一點,您首先需要將接收到的緩沖區轉換為所要求的格式,然后以浮點形式計算該值。

例如,如果音頻緩沖區格式是 S16LE(有符號的 16 位小端)並且您使用的是小端機器(很可能),那么您將執行以下操作:

   Int16 sample; // Range of data is +32767 -32768 or ~ +/- 1<<15 - 1
   float scale = (float)(1.0 / (double)(1 << (sizeof(sample) - 1)));
   for (int i = 0; i < len; i += sizeof(sample)) 
   {
      memcpy(&sample, &pcm[i], sizeof(sample)); // Use this so it'll work on machine that don't allow non-aligned access to char buffers
      float s = sample * scale;
      [...] // Do whatever you want with s
   }

編輯:您的代碼有問題。 首先,您請求 32 位浮點樣本(行as.format = AUDIO_F32;並首先調用SDL_OpenAudioDevice )。 然后,如果它失敗了,你會像上面的例子一樣要求 S16(有符號的 16 位)。 問題是你沒有跟蹤你會得到什么格式(它是浮動的嗎?是 S16 嗎?)。

因此,要么使用 F32 格式刪除第一個調用,只保留 S16 格式(並使用上面的代碼進行轉換)。 或者,將接受的格式存儲在某處並根據接受的格式采取不同的行動。

在 F32 的情況下,您可以通過如下轉換將pcm變量轉換為float*float * buffer = (float*)pcm;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM