2012-09-28 52 views
0

我試圖使自己的回聲墊,實際上它去好了,直到回聲部分添加兩個音頻信號中的Java/Android的

起初,我開始用聲音創建,它是偉大的,但是當我開始添加回聲效果聽起來很愚蠢。

守則

package com.echo; 

import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 

public class WavePlay { 

    private final static float duration = 1f; // seconds 
    private final static int sampleRate = 44100; 
    private final static int numSamples = (int) (duration * sampleRate); 
    private final static double sample[] = new double[numSamples]; 

    private static SourceDataLine line = null; 
    private static int freqOfTone = 30; 

    private static byte[] original; 

    public static void main(String[] args) { 

     AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
       sampleRate, 8, 1, 1, sampleRate, true); 

     DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); 

     try { 
      line = (SourceDataLine) AudioSystem.getLine(info); 
      line.open(format); 
     } catch (LineUnavailableException e) { 
      e.printStackTrace(); 
     } 

     for (int i = 0; i < numSamples; ++i) { 
      sample[i] = 255 * Math.sin(2 * Math.PI * i 
        /(sampleRate/freqOfTone)); 

     } 

     final byte generatedSnd[] = new byte[100000]; 

     original = new byte[generatedSnd.length]; 

     for (int i = 0; i < 20000; i++) { 

      generatedSnd[i] = (byte) (sample[i % sample.length] + 1); 

      original[i] = generatedSnd[i]; 

     } 

     // Echo 

     int delaySamples = 10000; 

     float decay = 0.3f; 

     for (int j = 0; j < 5; j++) { 
      for (int i = 0; i < generatedSnd.length; i++) { 

       if (i < delaySamples * (j + 1)) { 
        continue; 
       } 

       generatedSnd[i] += (byte) (original[i - delaySamples * (j + 1)] * decay); 

      } 

      decay *= 0.4; 
     } 

     // play 

     InputStream source = new ByteArrayInputStream(generatedSnd); 

     int numRead = 0; 
     byte[] buf = new byte[line.getBufferSize()]; 

     line.start(); 
     // read and play chunks of the audio 
     try { 
      while ((numRead = source.read(buf, 0, buf.length)) >= 0) { 
       int offset = 0; 
       while (offset < numRead) 
        offset += line.write(buf, offset, numRead - offset); 
      } 
     } catch (IOException e) { 
      System.out.println(e.getMessage()); 
     } 

     line.drain(); 
     line.stop(); 
     line.close(); 

     System.exit(0); 
    } 

} 

請運行該代碼,並告訴我是否有任何問題

感謝很多提前

回答

0

事實是,有幾個錯誤,該代碼以下產生更清晰的結果:

  • 值在寫緩衝區必須小於Byte.MAX_VALUE(如果寫在Android上採用短陣列的支持,您的偏移量將SHORT.MAX_VALUE)

  • 樣品創建以更清潔的方式來實現

守則

import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 

public class WavePlay { 

    public static void main(String[] args) { 

     float duration = 1f; // seconds 
     int sampleRate = 44100; 
     int numSamples = (int) (duration * sampleRate); 
     double sample[] = new double[numSamples]; 

     SourceDataLine line = null; 
     int freqOfTone = 300; 

     double[] original; 

     AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
       sampleRate, 8, 1, 1, sampleRate, true); 

     DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); 

     try { 
      line = (SourceDataLine) AudioSystem.getLine(info); 
      line.open(format); 
     } catch (LineUnavailableException e) { 
      e.printStackTrace(); 
     } 

     double increment = 2 * Math.PI * freqOfTone/sampleRate; 
     double angle = 0; 

     for (int i = 0; i < numSamples; ++i) { 
      sample[i] = (Math.sin(angle)) * Byte.MAX_VALUE; 
      angle += increment; 
     } 

     final double generatedSnd[] = new double[200000]; 

     original = new double[generatedSnd.length]; 

     for (int i = 0; i < 20000; i++) { 
      generatedSnd[i] = sample[i % sample.length]; 

      original[i] = generatedSnd[i]; 

     } 

     // Echo 

     int delaySamples = 20000; 

     float decay = 0.8f; 

     double maxValue = Byte.MAX_VALUE; 

     for (int j = 0; j < 10; j++) { 
      for (int i = 0; i < generatedSnd.length; i++) { 

       if (i < delaySamples * (j + 1)) { 
        continue; 
       } 

       generatedSnd[i] += original[i - delaySamples * (j + 1)] * decay; 
       if(generatedSnd[i] > maxValue){ 
        maxValue = generatedSnd[i]; 
       } 

      } 

      decay *= 0.5; 
     } 

     //scale to fit byte length (8 bit) 
     byte[] out = new byte[generatedSnd.length]; 

     for (int i = 0; i < out.length; i++) { 
      out[i] = (byte)(Byte.MAX_VALUE * generatedSnd[i]/maxValue); 
     } 

     // play 

     InputStream source = new ByteArrayInputStream(out); 

     int numRead = 0; 
     byte[] buf = new byte[line.getBufferSize()]; 

     line.start(); 
     // read and play chunks of the audio 
     try { 
      while ((numRead = source.read(buf, 0, buf.length)) >= 0) { 
       int offset = 0; 
       while (offset < numRead) 
        offset += line.write(buf, offset, numRead - offset); 
      } 
     } catch (IOException e) { 
      System.out.println(e.getMessage()); 
     } 

     line.drain(); 
     line.stop(); 
     line.close(); 

     System.exit(0); 
    } 

}