Playing an arbitrary tone with Android

后端 未结 10 2258
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 10:38

Is there any way to make Android emit a sound of arbitrary frequency (meaning, I don\'t want to have pre-recorded sound files)?

I\'ve looked around and ToneGenerator

10条回答
  •  礼貌的吻别
    2020-11-22 11:04

    Do major (16 notes)

     public class MainActivity extends AppCompatActivity {
    
      private double mInterval = 0.125;
      private int mSampleRate = 8000;
      private byte[] generatedSnd;
    
      private final double mStandardFreq = 440;
    
      Handler handler = new Handler();
      private AudioTrack audioTrack;
    
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      }
    
      @Override
      protected void onResume() {
        super.onResume();
    
        // Use a new tread as this can take a while
        final Thread thread = new Thread(new Runnable() {
            public void run() {
    
                byte[] tempByte = new byte[0];
                for (int i = 0; i < 16 ; i++ ){
                    double note = getNoteFrequencies(i);
                    byte[] tonByteNote = getTone(mInterval, mSampleRate, note);
                    tempByte = concat(tonByteNote, tempByte);
                }
                generatedSnd = tempByte;
    
                handler.post(new Runnable() {
                    public void run() {
                        playTrack(generatedSnd);
                    }
                });
            }
        });
        thread.start();
      }
    
      public byte[] concat(byte[] a, byte[] b) {
        int aLen = a.length;
        int bLen = b.length;
        byte[] c= new byte[aLen+bLen];
        System.arraycopy(a, 0, c, 0, aLen);
        System.arraycopy(b, 0, c, aLen, bLen);
        return c;
      }
    
      private double getNoteFrequencies(int index){
        return mStandardFreq * Math.pow(2, (double) index/12.0d);
      }
    
      private byte[] getTone(double duration, int rate, double frequencies){
    
        int maxLength = (int)(duration * rate);
        byte generatedTone[] = new byte[2 * maxLength];
    
        double[] sample = new double[maxLength];
        int idx = 0;
    
        for (int x = 0; x < maxLength; x++){
            sample[x] = sine(x, frequencies / rate);
        }
    
    
        for (final double dVal : sample) {
    
            final short val = (short) ((dVal * 32767));
    
            // in 16 bit wav PCM, first byte is the low order byte
            generatedTone[idx++] = (byte) (val & 0x00ff);
            generatedTone[idx++] = (byte) ((val & 0xff00) >>> 8);
    
        }
    
        return generatedTone;
    }
    
      private AudioTrack getAudioTrack(int length){
    
        if (audioTrack == null)
            audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                    mSampleRate, AudioFormat.CHANNEL_OUT_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, length,
                    AudioTrack.MODE_STATIC);
    
        return audioTrack;
      }
    
      private double sine(int x, double frequencies){
        return Math.sin(  2*Math.PI * x * frequencies);
      }
    
      void playTrack(byte[] generatedSnd){
        getAudioTrack(generatedSnd.length)
                .write(generatedSnd, 0, generatedSnd.length);
        audioTrack.play();
      }
    
    }
    

提交回复
热议问题