1

iPhoneでオーディオをリアルタイムで位相シフトすることは可能ですか?

マイクからリアルタイムで音声を出力する簡単なアプリケーションをセットアップしました。私がやろうとしているのは、このオーディオを処理すること、つまり位相シフトを行うことです。

続行する唯一の方法は、サンプル空間を取得し、FFT、位相シフト、および逆 fft を実行することですか?

vDSP ライブラリについては認識していますが、単純なタスクにはオーバーヘッドが多すぎるようです。

更新: 私は Elec Eng から DSP の基礎を持っています。はい、私は本当に位相シフトをしたいと思っています。周波数シフトやフィルターを行う必要はありません。後で実装する別のプロセスです。

4

5 に答える 5

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[]}
        *        .        *        |        *        |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |         *       |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |         *       |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |         *       |        *        .        *        
        *        .        *        |         *       |        *        .        *        
        *        .        *        |         *       |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |          *      |        *        .        *        
        *        .        *        |             *   |        *        .        *        
        *        .        *        |               * |        *        .        *        
                *.        *        |                *|        *        .        *        
                *.        *        |               * |        *        .        *        
                *.        *        |             *   |           *     .        *        
                *.        *        |          *      |                *.        *        
                *.        *        |        *        |              *  .        *        
                *.        *        |         *       |               * .        *        
                *.        *        |         *       |              *  .        *        
                *.        *        |         *       |               * .        *        
        *        .        *        |        *        |              *  .        *        
        *        .        *        |        *        |                *.        *        
        *        .        *        |         *       |           *     .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |        *        |        *        .        *        
        *        .        *        |         *       |        *        .        *        
        *        .        *        |        *        |        *        .        *        
于 2012-08-09T08:59:55.137 に答える
0

iOSデバイスでさまざまなオーディオ処理をリアルタイムで実行できるはずです。十分な処理能力があります。

おそらく、どのような位相シフトを実行したいかをより詳細に説明できます。続行するための「唯一の」方法がFFTを使用することであるということは厳密には真実ではありませんが、少なくともパフォーマンスとバッテリー寿命に関しては、それが最善の方法である可能性があります。

vDSPのオーバーヘッドが多すぎるように思われる場合、プロセッサのパフォーマンスを指しているのですか、それともエンジニアリングの努力を指しているのですか?私は同意します。主に、実際のデータ(入力信号など)を偶数の分割に再配置する必要があるレガシーインターフェイスが原因で、vDSPには望ましくないエンジニアリング作業があります。ただし、FFTデータの設定などの他の側面が必要です。それらはFFTの性質によって強制されます。

コンピューティングパフォーマンスは、vDSPルーチンで非常に優れているはずです。プロセッサのパフォーマンスまたはエンジニアリングの努力のいずれかで問題が発生した場合は、バグ(または機能の要求)を報告してください。

于 2012-08-08T17:28:32.273 に答える
0

iPhoneでオーディオをリアルタイムで位相シフトすることは可能ですか?

そうですね、しかしそれはおそらくあなたが実際にやりたいことではありません。(TJDのコメントを参照)

マイクからリアルタイムで音声を出力する簡単なアプリケーションをセットアップしました。私がやろうとしているのは、このオーディオを処理すること、つまり位相シフトを行うことです。

オーディオの処理は、位相シフトを行うことと同義ではありません。おそらく、「フィルタリング」したいですか?

続行する唯一の方法は、サンプル空間を取得し、FFT、位相シフト、および逆 fft を実行することですか?

あなたがやりたいことがオーディオをフィルタリングすることであると仮定すると、いいえ、FFTはお勧めしません。ウィンドウ処理、オーバーラップ/追加、パフォーマンスなど、多くの問題に苦労します。FFT はフィルターを設計するのに適した方法ではありません。

vDSP ライブラリについては認識していますが、単純なタスクにはオーバーヘッドが多すぎるようです。

私は vDSP を使用したことがありませんが、簡単に調べてみると、フィルタリングに適したソリューションとは思えません。適切なソリューションは、単純な biquad 関数を使用する可能性が高くなります。ここでそれらについて読むことができます:

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

ここに彼らのための素敵な「クックブック」があります:

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

于 2012-07-31T23:26:18.810 に答える
0

(リアルタイム順方向)位相シフトは単にオーディオサンプルの時間シフトであるため、DSPを必要としないという他の人たちに同意します。もちろん、リアルタイムの逆位相シフトには、タイムトラベルが必要になるため、DSP よりも多くの労力が必要になります。

一方、iPhone マイクのオーディオ サンプルの固定周波数シフトを実行する簡単で迅速な方法が必要です。実際には、たとえば 1 Hz 単位で数回の周波数シフトが発生します。iPhoneでそのタスクをすばやく簡単に実行する方法を知っている人はいますか?

于 2013-05-07T23:52:12.203 に答える
0

やりたいことは、出力に対応する必要があるのは、入力とカーネルの折りたたみ積分です。これは、インパルス入力の出力として見つけることができます。見つけたら、適切な数値積分法を使用して折りたたみ積分を実行します。これは、1 つの fft:s を 1 回だけ実行する必要があることを意味します。出力を継続的に提供するには、残りを継続的に実行する必要があります。

于 2012-07-31T20:01:32.907 に答える