11

AudioTrack を使用して、正弦波、方形波、のこぎり波を生成しようとしています。ただし、これが作成しているオーディオは、純粋な正弦波のようには聞こえませんが、何らかの他の波がオーバーレイされているようです。最初の例のメソッドを使用しながら、2 番目のコード例のように純粋な正弦波を取得するにはどうすればよいでしょうか? 上の例は、2 番目の例で使用されている演算の一部を移動するだけなので、同じ波を生成するべきではありませんか?

@Override
        protected Void doInBackground(Void... foo) {
            short[] buffer = new short[1024];
            this.track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
            float samples[] = new float[1024];

            this.track.play();

            while (true) {
                for (int i = 0; i < samples.length; i++) {
                    samples[i] = (float) Math.sin( (float)i * ((float)(2*Math.PI) * frequency / 44100));    //the part that makes this a sine wave....
                    buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
                }
                this.track.write( buffer, 0, samples.length );  //write to the audio buffer.... and start all over again!

            }           
        }

注:これにより、純粋な正弦波が得られます。

@Override
        protected Void doInBackground(Void... foo) {
            short[] buffer = new short[1024];
            this.track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
            float increment = (float)(2*Math.PI) * frequency / 44100; // angular increment for each sample
            float angle = 0;
            float samples[] = new float[1024];

            this.track.play();

            while (true) {
                for (int i = 0; i < samples.length; i++) {
                    samples[i] = (float) Math.sin(angle);   //the part that makes this a sine wave....
                    buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
                    angle += increment;
                }
                this.track.write( buffer, 0, samples.length );  //write to the audio buffer.... and start all over again!

            }           
        }

Martijn に感謝: 問題は、バッファ内の波長間で波が遮断されていることです。バッファ サイズを増やすと、2 番目の例の問題が解決されます。Math.PI * 2 算術演算がループの中で最も集中しているように見えるため、その値を 1 回だけ計算される外部変数に移動すると、すべてが解決されます。

4

3 に答える 3

2

コードを最適化してみてください

  1. バッファサイズを増やす
  2. バッファーを一度準備し、それを出力ストリームに書き換え続けます (これには、正弦波全体がバッファーに完全に収まるように、バッファーの完全なサイズを計算する計算が必要になります)。

なんで?バッファーの準備に時間がかかりすぎると思われるため、2 つのバッファー プッシュ間のラグが大きくなり、ノイズが発生している可能性があります。

于 2012-07-12T09:46:35.040 に答える
1

2 つのコード サンプルで確認できる唯一の重要な違いは、最初の例の方程式に整数 ( I) が含まれているため、おそらく整数 (浮動小数点ではない) 演算を行っていることです。これにより階段状の効果が生じ、波形に不要な高調波が追加されます。

方程式で単純Iに float にキャストすると、純粋な正弦波が生成されると思います。

samples[i] 
    = (float) Math.sin( (float)i * ((float)(2*Math.PI) * frequency / 44100));
于 2012-07-11T16:01:12.467 に答える
0

これらの答えはどれも問題を解決しません。バッファーの長さは、サンプル レートの倍数、または少なくとも 1 回転の長さである必要があります。物事を理解していることを示すために、それをたくさんの変数に分けてみましょう。

int sampleRate = 44100;
int bitsPerChannel = 16;
int bytesPerChannel = bitsPerChannel / 8;
int channelCount = 1;
int bytesPerSample = channelCount * bytesPerChannel;
int bytesPerRotation = sampleRate * bytesPerSample * (1d / (double) frequency);

次に、これを何倍にしbytesPerRotationても、事実は変わりません。つまり、サウンドにグリッチが発生することはありません。

于 2015-08-09T04:25:03.590 に答える