2014-09-06 6 views
0

У меня возникла проблема генерации гладкой волны синуса.Звуковая волна Android - негладкая и длительная проблема

Я сделал это несколько лет назад на C++, и все сработало отлично. Теперь я пытаюсь сделать это с помощью AudioTrack, и я не знаю, что не так.

Это мой тест:

Я хочу, чтобы произвести на пять второй пазухи волны, которая является гладкой (без трещин и т.п.). В течение одной секунды я генерирую 44100 выборок и разделяю их на пару буфера размером 8192 (вероятно, это причина трещин, но как я могу исправить это, не придавая большему размеру буфера). К сожалению, используя мой код, звук не является гладким и вместо 5 секунд занимает около 1 секунды. Я был бы благодарен за любую помощь. Пожалуйста, позвольте мне сейчас, если этого фрагмента недостаточно.

class Constants: 
    //<--- 
    public final static int SAMPLING = 44100; 
    public final static int DEFAULT_GEN_DURATION = 1000; 
    public final static int DEFAULT_NUM_SAMPLES = DEFAULT_GEN_DURATION * SAMPLING/1000; //44100   per second 
    public final static int DEFAULT_BUFFER_SIZE = 8192; 
    //---> 

    //preparing buffers to play; 
    Buffer buffer = new Buffer(); 
    short[] buffer_values = new short[Constants.DEFAULT_BUFFER_SIZE]; 
    float[] samples = new float[Constants.DEFAULT_BUFFER_SIZE]; 
    float d = (float) ((Constants.FREQUENCIES[index] * 2 * Math.PI)/Constants.SAMPLING); 


    int numSamples = Constants.DEFAULT_NUM_SAMPLES; //44100 per second - for test 
    float x = 0; 
    int index_in_buffer = 0; 

    for(int i = 0; i < numSamples; i++){ 
     if(index_in_buffer >= Constants.DEFAULT_BUFFER_SIZE - 1){ 
      buffer.setBufferShort(buffer_values); 
      buffer.setBufferSizeShort(index_in_buffer); 
      queue_with_data_AL.add(buffer); //add buffer to queue 
      buffer_values = new short[Constants.DEFAULT_BUFFER_SIZE]; 
      samples = new float[Constants.DEFAULT_BUFFER_SIZE]; 
      index_in_buffer = 0; 
     } 

    samples[index_in_buffer] = (float) Math.sin(x); 

    buffer_values[index_in_buffer] = (short) (samples[index_in_buffer] * Short.MAX_VALUE); 

    x += d; 
    index_in_buffer++; 
    } 

    buffer.setBufferShort(buffer_values); 
     buffer.setBufferSizeShort(index_in_buffer+1); 
     queue_with_data_AL.add(buffer); 

     index_in_buffer = 0; 

    } 


    //class AudioPlayer 

    public AudioPlayer(int sampleRate) { //44100 

    int minSize = AudioTrack.getMinBufferSize(sampleRate, 
      AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); 

    audiotrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, 
      AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, 
      minSize, AudioTrack.MODE_STREAM); 
    } 


    public void play(byte[] audioData, int sizeOfBuffer) { 
      audiotrack.write(audioData, 0, sizeOfBuffer); 
    } 

    public void start() { 
    if (state == Constants.STOP_STATE) { 
    state = Constants.START_STATE; 
    int startLength = 0; 
    while (state == Constants.START_STATE) { 
     Buffer buffer = getBufferFromQueueAL(); //getting buffer from prepared list 
     if (buffer != null) { 
     short[] data = buffer.getBufferShort(); 
     int size_of_data = buffer.getBufferSizeShort(); 
     if (data != null) { 
      int len = audiotrack.write(data, 0, size_of_data); 
      if (startLength == 0) { 
       audiotrack.play(); 
      } 

      startLength += len; 
     } else { 
      break; 
     } 

    } else { 
     MessagesLog.e(TAG, "get null data"); 
     break; 
    } 
    } 

    if (audiotrack != null) { 
      audiotrack.pause(); 
      audiotrack.flush(); 
      audiotrack.stop(); 
    } 
    } 
    } 

ответ

0

Я нашел решение самостоятельно. После добавления Buffer в queue_with_data_AL я забыл создать новый экземпляр объекта Buffer. Таким образом, в очереди была пара буфера с одним и тем же экземпляром, поэтому синусовая волна не была непрерывной.

Спасибо, если кто-то пытался решить мою проблему. К сожалению, это была моя ошибка программирования.

С уважением.

0

Вы играете всего 1 секунду, потому что 44100 выборок на частоте 44100 Гц дают ровно 1 секунду звука.

Вам необходимо сгенерировать в 5 раз больше образцов, если вы хотите воспроизвести 5 секунд звука (например, умножьте DEFAULT_NUM_SAMPLES на 5) в свой код.

+1

Извините, я не был достаточно ясен. Генератор синусовой волны находился в цикле, который повторял процедуру 5 раз. Несколько минут назад я добавил ответ, что не так. В любом случае, спасибо. – user1683637