Playing an arbitrary tone with Android

后端 未结 10 2259
伪装坚强ぢ
伪装坚强ぢ 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 10:46

    Improving on the above code:

    Add amplitude ramp up and ramp down to avoid the clicks.

    Add code to determine when the tack has finished playing.

    double duration = 1;            // seconds
    double freqOfTone = 1000;       // hz
    int sampleRate = 8000;          // a number
    
    double dnumSamples = duration * sampleRate;
    dnumSamples = Math.ceil(dnumSamples);
    int numSamples = (int) dnumSamples;
    double sample[] = new double[numSamples];
    byte generatedSnd[] = new byte[2 * numSamples];
    
    
    for (int i = 0; i < numSamples; ++i) {    // Fill the sample array
        sample[i] = Math.sin(freqOfTone * 2 * Math.PI * i / (sampleRate));
    }
    
    // convert to 16 bit pcm sound array
    // assumes the sample buffer is normalized.
    // convert to 16 bit pcm sound array
    // assumes the sample buffer is normalised.
    int idx = 0;
    int i = 0 ;
    
    int ramp = numSamples / 20 ;                                     // Amplitude ramp as a percent of sample count
    
    
    for (i = 0; i< ramp; ++i) {                                      // Ramp amplitude up (to avoid clicks)
        double dVal = sample[i];
                                                                     // Ramp up to maximum
        final short val = (short) ((dVal * 32767 * i/ramp));
                                                                     // in 16 bit wav PCM, first byte is the low order byte
        generatedSnd[idx++] = (byte) (val & 0x00ff);
        generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
    }
    
    
    for (i = i; i< numSamples - ramp; ++i) {                         // Max amplitude for most of the samples
        double dVal = sample[i];
                                                                     // scale to maximum amplitude
        final short val = (short) ((dVal * 32767));
                                                                     // in 16 bit wav PCM, first byte is the low order byte
        generatedSnd[idx++] = (byte) (val & 0x00ff);
        generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
    }
    
    for (i = i; i< numSamples; ++i) {                                // Ramp amplitude down
        double dVal = sample[i];
                                                                     // Ramp down to zero
        final short val = (short) ((dVal * 32767 * (numSamples-i)/ramp ));
                                                                     // in 16 bit wav PCM, first byte is the low order byte
        generatedSnd[idx++] = (byte) (val & 0x00ff);
        generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
    }
    
    AudioTrack audioTrack = null;                                    // Get audio track
    try {
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
            sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
            AudioFormat.ENCODING_PCM_16BIT, (int)numSamples*2,
            AudioTrack.MODE_STATIC);
        audioTrack.write(generatedSnd, 0, generatedSnd.length);        // Load the track
        audioTrack.play();                                             // Play the track
    }
    catch (Exception e){
        RunTimeError("Error: " + e);
        return false;
    }
    
    int x =0;
    do{                                                              // Monitor playback to find when done
        if (audioTrack != null) 
            x = audioTrack.getPlaybackHeadPosition(); 
        else 
            x = numSamples;
    } while (x

提交回复
热议问题