2017-02-20 37 views
0

以下是我用于在android studio中生成连续正弦波的一些代码。整件事在一个线程中运行。我的问题是:当我调用audio.write()时,可能仍然存在于缓冲区中的数据会发生什么?它会转储旧样本并写入一个新的样本,还是会将新样本数组附加到其余样本?AudioTrack.write()中的缓冲区中的数据会发生什么

int buffSize = AudioTrack.getMinBufferSize(sr, AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT); 
      //create the AudioTrack object 
      AudioTrack audio = new AudioTrack( AudioManager.STREAM_MUSIC, 
               sr, 
               AudioFormat.CHANNEL_OUT_MONO, 
               AudioFormat.ENCODING_PCM_16BIT, 
               buffSize, 
               AudioTrack.MODE_STREAM); 
      //initialise values for synthesis 
      short samples[]= new short[buffSize]; //array the same size as buffer 
      int amp=10000;       //amplitude of the waveform 
      double twopi = 8.*Math.tan(1.);   //2*pi 
      double fr = 440;      //the frequency to create 
      double ph = 0;       //phase shift 
      //start audio 
      audio.play(); 
      //synthesis loop 
      while (isRunning) 
      { 
       fr=440+4.4*sliderVal; 

       for (int i=0;i<buffSize;i++) 
       { 
         samples[i]=(short)(amp*Math.sin(ph)); 
         ph+=twopi*fr/sr; 
       } 
       audio.write(samples,0,buffSize); 
      } 
      //stop the audio track 
      audio.stop(); 
      audio.release(); 

回答

0

您正确设置基于设备能力的缓冲区大小 - 这对于最小化延迟非常重要。

然后,您正在构建缓冲区并将它们分块到硬件中,以便可以听到它们。每个人都没有“在那里”。缓冲区被建立,然后你每次在track.write中写入整个缓冲区。

以下是我的generateTone例程,与您的很类似。所谓的像这样与赫兹频率和持续时间以毫秒为:

AudioTrack sound = generateTone(440, 250); 

而且generateTone类:

private AudioTrack generateTone(double freqHz, int durationMs) { 
    int count = (int)(44100.0 * 2.0 * (durationMs/1000.0)) & ~1; 
    short[] samples = new short[count]; 
    for(int i = 0; i < count; i += 2){ 
     short sample = (short)(Math.sin(2 * Math.PI * i/(44100.0/freqHz)) * 0x7FFF); 
     samples[i + 0] = sample; 
     samples[i + 1] = sample; 
    } 
    AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, 
    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, 
    count * (Short.SIZE/8), AudioTrack.MODE_STATIC); 
    track.write(samples, 0, count); 
    return track; 
} 

AudioTrack很酷,因为如果你有合适的算法中,你可以创建任何类型的声音。 Puredata和Csound使得它在Android上更容易。

(我在我的书的Android应用软件开发收集的实际项目上写道音频一个大章节。)

+0

感谢您的反馈,让我在正确的轨道上。在写下一个x个样本之前,是否有任何情况需要同步来确保设备已经播放了x个样本? – Johan

+0

很高兴听到!那么,你不必同步,但你必须“保持”。如果你不能足够快地填充缓冲区块,那么你会跳过或退出。你知道发生这种情况是因为你可以听到它。由于音频延迟问题,这是Android中的一个大问题。有史以来生产的每台Android设备比每台iOS设备产生的延迟都要高。很难相信,但是的确如此。有一个名为AudioBuffersSize的非常好的Google开源应用程序,可以显示设备的功能,例如缓冲区大小和采样率。然后,您可以在音频应用程序中正确设置它们。 –

+0

谢谢马克!我还没有遇到过这个问题。编写一个单独的,轻量级的writeToBuffer线程会是一个好主意吗? – Johan

相关问题