20

Cocoa で、さまざまなズーム オプションを備えたオーディオ波形エディターを作成しています。幅を最大にすると、曲全体の波形が表示されます (最大 1,000 万サンプルが表示されます)。最も狭い範囲では、音波のピクセル精度の表現が表示されます (1 ビューで最大 1,000 サンプル)。これらのズーム レベル間をスムーズに移行できるようにしたいと考えています。Ableton Live などの一部の商用エディターは、非常に安価な方法でこれを行っているようです。

私の現在の実装は、希望するズーム範囲を満たしていますが、非効率的で途切れ途切れです。このデザインは、クォーツを使用した波形の描画に関する次の優れた記事に大きく影響を受けています。

http://supermegaultragroovy.com/blog/2009/10/06/drawing-waveforms/

さまざまな削減レベルでオーディオ ファイル用に複数の CGMutablePathRef を作成します。完全にズームアウトすると、x 千サンプルごとに 1 つのポイントに縮小されたパスを使用します。完全にズームインすると、すべてのサンプルのポイントを含むそのパスを使用します。削減レベルの間にいるときは、パスを水平方向にスケーリングします。これにより機能しますが、それでもかなりコストがかかり、削減レベル間を移行するときにアーティファクトが表示されます。

これをより安価にする方法についての 1 つの考えは、アンチエイリアシングを取り除くことです。私のエディタの波形はアンチエイリアスされていますが、Ableton の波形はそうではありません (以下の比較を参照)。 ここに画像の説明を入力 ここに画像の説明を入力

CGMutablePathRef のアンチエイリアシングをオフにする方法がわかりません。Cocoa の世界で CGMutablePathRef に代わるアンチエイリアスのない代替手段はありますか? そうでない場合、巨大な線をより効率的に描画するためのコースに私を設定する可能性のある OpenGL クラスまたはサンプル コードを知っている人はいますか?

2014 年 1 月 21 日更新:まさに私が探していた機能を備えた優れたライブラリがあります: https://github.com/syedhali/EZAudio

4

2 に答える 2

6

アプリで CGContextMoveToPoint+CGContextAddLineToPoint+CGContextStrokePath を使用しています。オーバービュー用に事前に計算されたバッキング バッファーを使用して描画する、画面上のポイントごとに 1 つのポイント。バッファーには描画する正確なポイントが含まれており、(ズーム/スケールに基づいて) 信号の補間表現を使用します。画像バッファにレンダリングすれば、より高速で見栄えが良くなる可能性がありますが、苦情はありませんでした。正しく設定すれば、セカンダリ スレッドからこれらすべてを計算してレンダリングできます。

アンチエイリアシングは、グラフィック コンテキストに関係します。

CGFloat (CGPaths のネイティブ入力) は、概要、中間表現、および波形概要の計算には過剰です。16 ビットで十分です。もちろん、CG 呼び出しに渡すときは CGFloat に変換する必要があります。

どこに時間が費やされているかを知るためにプロファイルを作成する必要があります。最も時間がかかる部分に注目してください。また、必要なときに必要なものだけを描画し、可能な場合はオーバーレイ/アニメーションを避けるようにしてください。オーバーレイが必要な場合は、イメージ/バッファーにレンダリングし、必要に応じて更新することをお勧めします。サーフェスが大きい場合、表示を複数の描画サーフェスに分割すると役立つ場合があります。

semi-OT: ableton の s+h 値の使用により、これはわずかに高速になる可能性がありますが、オプションとしては非常に気に入っています。実装が線形補間を使用している場合 (外観に基づいて線形補間を使用している可能性があります)、より直感的なアプローチを検討してください。線形補間は少しチートであり、プロのアプリを開発している場合にユーザーが期待するものではありません。

于 2011-01-31T10:25:58.860 に答える
2

アンチエイリアシングの特定の問題に関連して。Quartz では、描画時にコンテキストにアンチエイリアスが適用されます。CGPathRef は、描画コンテキストに依存しません。したがって、同じ CGPathRef をアンチエイリアス処理されたコンテキストまたはアンチエイリアス処理されていないコンテキストにレンダリングできます。たとえば、アニメーション中にアンチエイリアシングを無効にするには:

CGContextRef context = UIGraphicsGetCurrentContext();
GMutablePathRef fill_path = CGPathCreateMutable();
// Fill the path with the wave
...

CGContextAddPath(context, fill_path);
if ([self animating])
    CGContextSetAllowsAntialiasing(context, NO);
else
    CGContextSetAllowsAntialiasing(context, YES);
// Do the drawing
CGContextDrawPath(context, kCGPathStroke);
于 2011-01-31T09:58:13.827 に答える