-1

指定した音量と周波数でサウンド (トーン) を再生したいが、再生時間を 2 秒に固定したい。

私のコードはここにあるものと似ています。

            double freq, volume;
            WaveTone tone = new WaveTone(freq, volume);
            stream = new BlockAlignReductionStream(tone);
            output = new DirectSoundOut();
            output.Init(stream);
            output.Play();

上記の DirectSoundOut() でレイテンシーを使用しようとしましたが、期待どおりに機能しませんでした。再生ごとに周波数と音量を動的に変更する必要があります。

トーンの正確な再生時間を知る必要があります。

4

1 に答える 1

0

このWaveToneクラス (私がググったばかりのものの 1 つを使用していると仮定します) は、おそらく無限のデータ ストリームを提供します。出力を特定の期間に制限する場合は、特定の量のデータを別のバッファー/ストリームにロードするかWaveTone、期間を過ぎたデータの生成を停止するようにクラスを変更する必要があります。

このようなもの:

class WaveTone : WaveStream
{
    readonly WaveFormat Format;
    public readonly double Frequency;
    public readonly double Amplitude;
    public readonly double Duration;

    readonly long streamLength;

    long pos;

    const double timeIncr = 1 / 44100.0;
    readonly double sinMult;

    public WaveTone(double freq, double amp)
        : this(freq, amp, 0)
    { }

    public WaveTone(double freq, double amp, double dur)
    {
        Format = new WaveFormat(44100, 16, 1);
        Frequency = freq;
        Amplitude = Math.Min(1, Math.Max(0, amp));
        Duration = dur;

        streamLength = Duration == 0 ? long.MaxValue : (long)(44100 * 2 * Duration);

        pos = 0;

        sinMult = Math.PI * 2 * Frequency;
    }

    public override WaveFormat WaveFormat
    {
        get { return Format; }
    }

    public override long Length
    {
        get { return streamLength; }
    }

    public override long Position
    {
        get { return pos; }
        set { pos = value; }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (pos >= streamLength)
            return 0;
        int nSamples = count / 2;
        if ((pos + nSamples * 2) > streamLength)
            nSamples = (int)(streamLength - pos) / 2;

        double time = pos / (44100 * 2.0);
        int rc = 0;
        for (int i = 0; i < nSamples; i++, time += timeIncr, ++rc, pos += 2)
        {
            double val = Amplitude * Math.Sin(sinMult * time);
            short sval = (short)(Math.Round(val * (short.MaxValue - 1)));
            buffer[offset + i * 2] = (byte)(sval & 0xFF);
            buffer[offset + i * 2 + 1] = (byte)((sval >> 8) & 0xFF);
        }

        return rc * 2;
    }
}
于 2013-08-04T23:31:37.617 に答える