音頻 float 32 48KHz 和 signed int 16 16KHz 的相互轉換


float 32 48KHz 轉 signed int 16 16KHz

采樣率,是一秒內含有多少樣本數量,48K則代表一秒內有48000個采樣點;16K,則代表一秒內有16000個采樣點。

48K轉16K是從高到低的轉換,只需要丟棄部分樣本即可完成轉換,16/48=3,故選擇每三幀取一幀。

 

float32格式的音頻,波形在±1之內,區間為(-1.0, +1.0);int16,波形區間(-32766, 32767),因而轉換過程只需要將每個采樣點乘以32767.0后取整即可。

 

float** adata = (float**)audio->data;    // 原始的48K float數據

short* sbuf = (short*)malloc(sizeof(short) * audio->frames);    // 轉換后的結果

for (int i = 0; i < audio->frames; ++i) {
    //每三幀留一幀,完成采樣率轉換
    if (i % 3 != 0)
        continue;

    // 對於超出int16范圍的結果規定取int16的極值,防止溢出(在波形種會產生豎線雜音)
    if (adata[0][i] < -0.999999f)
        sbuf[i / 3] = INT16_MIN;
    else if (adata[0][i] > 0.999999f)
        sbuf[i / 3] = INT16_MAX;
    else
        sbuf[i / 3] = adata[0][i] * (32767.0f);
}

// ......

free(sbuf);

signed int 16 16KHz 轉 float 32 48KHz

反向轉換相對麻煩

由於是由少到多,需要在兩幀之間進行插值,這里采用平均插值,即將兩幀之間的差值均分后按大小插入相對維持了波形的趨勢。

s16轉回float相對簡單,除回去就可以了。

大家不要像我一樣new 和 malloc 混合使用,這里只是思路

 

int16_t* ba = (int16_t*)i16pcm;        // 需要轉換的原始數據

int n = 48/16;    // 采樣率的放大倍率

// 樣本總數量
int baFrameCount = bar.size() / sizeof(int16_t);
int if48FrameCount  = bar.size() * n / sizeof(int16_t);

int16_t* i48pcm = new int16_t[if48FrameCount];

// 插值處理,16K轉48K
for (int i = 0; i < baFrameCount; ++i) {
    for (int j = 0; j < n; ++j) {
        i48pcm[i*n+j] = ((i >(baFrameCount) - 2) ?
            ba[i] + (0 - ba[i]) / n * j:
            ba[i] + ((ba[i + 1] - ba[i]) / n * j));
    }
}

// int16 轉 float
float* f48pcm = (float*)malloc(if48FrameCount*sizeof(float));
for (int i = 0; i < if48FrameCount; ++i) {
    f48pcm[i] = (float)i48pcm[i] / 32767.0f;
}
delete[] i48pcm;

// ......

free(f48pcm);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM