2012-07-31 94 views
1

是否可以在iPhone上實時移相音頻?iPhone音頻相移

我有一個簡單的應用程序設置,實時輸出麥克風的音頻。我試圖做的是處理這個音頻,即做相移。

我正確的唯一方法就是採取我的樣本空間,做一個FFT,相移,然後逆fft?

我知道vDSP庫,但它看起來像一個簡單的任務太多的開銷。

更新:我有一個來自Elec Eng的DSP基礎,是的,我真的想做一個相位轉換。我不需要進行頻率轉換或過濾,他們是我將在稍後實施的單獨過程。

+0

你是指頻移?相移是毫無意義和瑣碎的。這只是原版的延遲版本。 – TJD 2012-07-31 21:38:04

+0

是的,我想要相移。 – Colin 2012-08-01 19:12:37

+0

如果您只想執行相移,則根本不需要任何DSP,因爲這只是輸入的時間延遲。只需讀取音頻數據並輸出即可 - 這會爲您帶來相位轉換。 – duskwuff 2012-08-08 17:33:40

回答

3

是的,這是一種方法。

此示例C代碼表示它:

#include <stdio.h> 
#include <math.h> 

#ifndef M_PI 
#define M_PI 3.14159265358979324 
#endif 

typedef struct 
{ 
    double x, y; 
} tComplex; 

tComplex complexAdd(const tComplex* a, const tComplex* b) 
{ 
    tComplex c; 
    c.x = a->x + b->x; 
    c.y = a->y + b->y; 
    return c; 
} 

tComplex complexMul(const tComplex* a, const tComplex* b) 
{ 
    tComplex c; 
    c.x = a->x * b->x - a->y * b->y; 
    c.y = a->x * b->y + a->y * b->x; 
    return c; 
} 

void dft(tComplex out[], const tComplex in[], size_t n, int direction) 
{ 
    size_t k, i; 
    for (k = 0; k < n; k++) 
    { 
    tComplex r = { 0, 0 }, e; 
    for (i = 0; i < n; i++) 
    { 
     e.x = cos(-2 * direction * M_PI/n * ((double)k - n/2) * ((double)i - n/2)); 
     e.y = sin(-2 * direction * M_PI/n * ((double)k - n/2) * ((double)i - n/2)); 
     e = complexMul(&e, &in[i]); 
     r = complexAdd(&r, &e); 
    } 
    out[k] = r; 
    } 
} 

double maxAbs(const tComplex in[], size_t n) 
{ 
    double m = 0; 
    while (n--) 
    { 
    double a = hypot(in->x, in->y); 
    if (m < a) m = a; 
    in++; 
    } 
    return m; 
} 

#define SAMPLE_CNT 32 
#define SAMPLE_SHIFT 3 

int main(void) 
{ 
    tComplex signalIn[SAMPLE_CNT]; 
    tComplex signalOut[SAMPLE_CNT]; 
    tComplex tmp[SAMPLE_CNT]; 
    int i; 

    // signalIn[] = square pulse 
    for (i = 0; i < SAMPLE_CNT; i++) 
    { 
    signalIn[i].x = ((i - SAMPLE_CNT/2) >= 0) * ((i - SAMPLE_CNT/2) < SAMPLE_CNT/4); 
    signalIn[i].y = 0; 
    } 

    // tmp[] = DFT{signalIn[]} 
    dft(tmp, signalIn, SAMPLE_CNT, 1); 

    // tmp[] = DFT{signalIn[]} * exp(j * 2 * PI * f * TimeShift) 
    for (i = 0; i < SAMPLE_CNT; i++) 
    { 
    tComplex e; 
    e.x = cos(2 * M_PI * (i - SAMPLE_CNT/2) * SAMPLE_SHIFT/SAMPLE_CNT); 
    e.y = -sin(2 * M_PI * (i - SAMPLE_CNT/2) * SAMPLE_SHIFT/SAMPLE_CNT); 
    tmp[i] = complexMul(&tmp[i], &e); 
    } 

    // signalOut[] = IDFT{tmp[]} 
    dft(signalOut, tmp, SAMPLE_CNT, -1); 

    printf("  Re{In[]} .  Im{In[]} |" 
     " |DFT{In[]}| |" 
     " Re{Out[]} . Im{Out[]}\n"); 

    for (i = 0; i < SAMPLE_CNT; i++) 
    { 
    int j, s; 

    s = signalIn[i].x/maxAbs(signalIn, SAMPLE_CNT) * 8 + .5; 
    for (j = -8; j <= 8; j++) printf("%c", " *"[s == j]); 
    printf("."); 
    s = signalIn[i].y/maxAbs(signalIn, SAMPLE_CNT) * 8 + .5; 
    for (j = -8; j <= 8; j++) printf("%c", " *"[s == j]); 

    printf("|"); 

    s = hypot(tmp[i].x, tmp[i].y)/maxAbs(tmp, SAMPLE_CNT) * 8; 
    for (j = -8; j <= 8; j++) printf("%c", " *"[s == j]); 

    printf("|"); 

    s = signalOut[i].x/maxAbs(signalOut, SAMPLE_CNT) * 8 + .5; 
    for (j = -8; j <= 8; j++) printf("%c", " *"[s == j]); 
    printf("."); 
    s = signalOut[i].y/maxAbs(signalOut, SAMPLE_CNT) * 8 + .5; 
    for (j = -8; j <= 8; j++) printf("%c", " *"[s == j]); 

    printf("\n"); 
    } 

    return 0; 
} 

輸出:

 Re{In[]} .  Im{In[]} | |DFT{In[]}| | Re{Out[]} . Im{Out[]} 
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |    * |  *  .  *   
     *  .  *  |    * |  *  .  *   
       *.  *  |    *|  *  .  *   
       *.  *  |    * |  *  .  *   
       *.  *  |    * |  *  .  *   
       *.  *  |   *  |    *.  *   
       *.  *  |  *  |    *.  *   
       *.  *  |   *  |    *.  *   
       *.  *  |   *  |    *.  *   
       *.  *  |   *  |    *.  *   
     *  .  *  |  *  |    *.  *   
     *  .  *  |  *  |    *.  *   
     *  .  *  |   *  |    *.  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   

可以看到,輸出是由SAMPLE_SHIFT樣品(3,在這裏)在時間上偏移的輸入的複製品。

您也可以將SAMPLE_SHIFT更改爲非整數值,從而得到一個小數的樣本。

輸出,用於SAMPLE_SHIFT = 2.5:

 Re{In[]} .  Im{In[]} | |DFT{In[]}| | Re{Out[]} . Im{Out[]} 
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |    * |  *  .  *   
     *  .  *  |    * |  *  .  *   
       *.  *  |    *|  *  .  *   
       *.  *  |    * |  *  .  *   
       *.  *  |    * |   *  .  *   
       *.  *  |   *  |    *.  *   
       *.  *  |  *  |    * .  *   
       *.  *  |   *  |    * .  *   
       *.  *  |   *  |    * .  *   
       *.  *  |   *  |    * .  *   
     *  .  *  |  *  |    * .  *   
     *  .  *  |  *  |    *.  *   
     *  .  *  |   *  |   *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
     *  .  *  |   *  |  *  .  *   
     *  .  *  |  *  |  *  .  *   
0

你想做什麼應該對應的輸出是一個內核輸入的摺疊積分。它可以作爲脈衝輸入的輸出。如果您能找到它,請使用適當的數字積分方法進行摺疊積分。這意味着只需要完成一次,剩下的工作應該連續完成,以便連續輸出。

+0

謝謝Per Arve。我在DSP中有一個基礎,是的,我確實想要做一個實時的相移(或儘可能接近)。除此之外,我也將進行過濾。 – Colin 2012-08-01 19:10:59

0

是否可以在iPhone上實時移相音頻?

嗯,是的,但這可能不是你真正想要做的。 (見TJD的評論)

我有一個簡單的應用程序設置,實時輸出麥克風的音頻。我試圖做的是處理這個音頻,即做相移。

處理音頻與進行相移並不是同義的。也許你想「過濾」?

我正確的唯一方法是採取我的樣本空間,做FFT,相移,然後逆fft?

假設你想要做的是過濾音頻,然後不,我不推薦FFT。您將面臨許多問題,如窗口,重疊/添加和性能。 FFT不是設計濾波器的好方法。

我知道vDSP庫,但它似乎是一個簡單的任務太多的開銷。

我從來沒有使用vDSP,但從快速檢查看,它看起來不像過濾的正確解決方案。正確的解決方案更可能使用簡單的雙二次函數。你可以在這裏讀到他們:

http://en.wikipedia.org/wiki/Digital_biquad_filter

,並有一個很好的「食譜」爲他們在這裏:

http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

+0

謝謝比約恩。我在DSP中有一個基礎,是的,我確實想要做一個實時的相移(或儘可能接近)。除此之外,我也將進行過濾。 – Colin 2012-08-01 19:10:31

+0

也許你有一個全通濾波器?我上面所說的一切都適用於此。 – 2012-08-01 22:27:34

0

應該可以做各種真實的音頻處理時間在iOS設備上。有足夠的處理能力。

也許你可以更詳細地描述你想要做什麼樣的相移。 「唯一」的方式是使用FFT,但這可能是最好的方式,至少在性能和電池壽命方面並不是絕對正確的。

當你說vDSP似乎有太多開銷時,你是指處理器性能還是工程量?我同意,vDSP有一些不希望的工程努力,主要是由於傳統接口需要真實數據(例如輸入信號)重新排列成偶數分割。但是,其他方面(例如FFT數據的設置)是必需的;他們被FFT的性質所強制。

vDSP例程的計算性能應該非常好。如果遇到困難,無論是處理器性能還是工程設計,請致電report bugs(或功能請求)。

0

我與其他同意,一個(實時向前)相移不需要DSP,因爲它只是在音頻樣本的時移。當然,實時逆向移相需要比DSP更多的努力,因爲它需要時間旅行。

另一方面,我需要一個簡單的快速方法來執行iphone麥克風音頻樣本的固定頻率轉換。實際上有幾個頻率位移,例如1Hz增量或其左右。任何人都知道在iPhone上執行該任務的快捷方式?