2017-02-20 1 views
0

Вот код, который я использую для создания непрерывной синусоидальной волны в студии android. Все это работает в потоке. Мой вопрос: когда я вызываю 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.

Ниже приведена моя процедура генерации текста, очень похожая на вашу. Вызывается, как например с частотой в Гц и длительность в мс:

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 это круто, потому что вы можете создать любой тип звука, если у вас есть право Algo. Pureata и Csound делают это намного проще, чем на Android.

(я написал большую главу о Audio в моей книге Android Software Развитие- сборник практических проектов.)

+0

Спасибо за обратную связь, у меня на правильный путь. Существуют ли случаи, когда синхронизация необходима для обеспечения того, чтобы устройство воспроизводило образцы x перед записью следующих x образцов? – Johan

+0

Рад это слышать! Ну, вам не нужно синхронизировать, но вам нужно «идти в ногу». Если вы не можете быстро заполнить блоки буферизации, вы получите пропуск или выпад. Вы знаете, что это происходит, потому что вы можете это услышать. Это большая проблема в Android из-за проблем с задержкой звука. Каждое устройство Android, когда-либо производившееся, имеет более высокую задержку, чем каждое устройство iOS. Тяжело поверить, но это правда. Существует действительно хорошее приложение с открытым исходным кодом Google, называемое AudioBuffersSize, которое показывает возможности устройства, такие как буферизация и выборка. Затем вы можете правильно установить их в своем звуковом приложении. –

+0

Спасибо, Марк! Я еще не сталкивался с этой проблемой. Было бы неплохо написать отдельный, легкий поток writeToBuffer? – Johan

Смежные вопросы