2

私は卒業のためにサウンドエディタを書いています。MP3、WAV、OGG などのファイルからサンプルを抽出し、エコー、フランジャーなどの DSP エフェクトを追加するためにBASSを使用しています。単純に言えば、ポジション 1 からポジション 2 にエフェクトを適用するフレームワークを作成し、カット/ペースト管理を行いました。

今私の問題は、曲の波形表現を描画し、波形の選択部分などをズームイン/ズームアウトする機能を持つCool Edit Proのこのコントロールと同様のコントロールを作成したいということです。選択後、私はできます次のようにします。

TInterval EditZone = WaveForm->GetSelection();

TInterval の形式は次のとおりです。

struct TInterval
{
    long Start;
    long End;
}

私は洗練された描画に関しては初心者なので、ズームイン/ズームアウト機能を備えたBASSから返されたサンプルデータを使用して、曲の波形表現を作成する方法に関するヒントをいただければ幸いです.

私は C++ でプロジェクトを書いていますが、C# と Delphi コードは理解できるので、必要に応じて最後の 2 つの言語でスニペットを投稿することもできます :)

ありがとう DrOptix

4

4 に答える 4

0

オープンソースの NAudio パッケージの使用 -

public class WavReader2
{
    private readonly WaveFileReader _objStream;

    public WavReader2(String sPath)
    {
        _objStream = new WaveFileReader(sPath);
    }

    public List<SampleRangeValue> GetPixelGraph(int iSamplesPerPixel)
    {
        List<SampleRangeValue> colOutputValues = new List<SampleRangeValue>();

        if (_objStream != null)
        {
            _objStream.Position = 0;
            int iBytesPerSample = (_objStream.WaveFormat.BitsPerSample / 8) * _objStream.WaveFormat.Channels;
            int iNumPixels = (int)Math.Ceiling(_objStream.SampleCount/(double)iSamplesPerPixel);

            byte[] aryWaveData = new byte[iSamplesPerPixel * iBytesPerSample];
            _objStream.Position = 0; // startPosition + (e.ClipRectangle.Left * iBytesPerSample * iSamplesPerPixel);

            for (float iPixelNum = 0; iPixelNum < iNumPixels; iPixelNum += 1)
            {
                short iCurrentLowValue = 0;
                short iCurrentHighValue = 0;
                int iBytesRead = _objStream.Read(aryWaveData, 0, iSamplesPerPixel * iBytesPerSample);
                if (iBytesRead == 0)
                    break;

                List<short> colValues = new List<short>();
                for (int n = 0; n < iBytesRead; n += 2)
                {
                    short iSampleValue = BitConverter.ToInt16(aryWaveData, n);
                    colValues.Add(iSampleValue);
                }

                float fLowPercent =  (float)((float)colValues.Min() /ushort.MaxValue);
                float fHighPercent = (float)((float)colValues.Max() / ushort.MaxValue);

                colOutputValues.Add(new SampleRangeValue(fHighPercent, fLowPercent));
            }
        }

        return colOutputValues;
    }
}

public struct SampleRangeValue
{
    public float HighPercent;
    public float LowPercent;
    public SampleRangeValue(float fHigh, float fLow)
    {
        HighPercent = fHigh;
        LowPercent = fLow;
    }
}
于 2012-02-16T04:22:08.973 に答える
0

サンプルポイントを2つのキャンバスにプロットするだけではありませんか? ファイルの 1 秒あたりのサンプル数を把握し (ヘッダーから読み取る)、その値を y 軸にプロットします。ズームインおよびズームアウトできるようにするため、ピクセルあたりのサンプル数 (ズーム レベル) を制御する必要があります。次に、ピクセルごとにこれらのサンプル ポイントの平均を取得します (たとえば、ピクセルごとに 5 つのサンプルがある場合は、5 ポイントごとの平均を取得します。次に、2D 描画 API を使用してポイント間に線を描画できます。

于 2010-02-21T08:25:07.923 に答える