2014-09-28 22 views
7

Tôi đang cố gắng tạo một ứng dụng ghi âm cuộc gọi trong Android. Tôi đang sử dụng loa để ghi cả âm thanh đường lên và đường xuống. Vấn đề duy nhất tôi phải đối mặt là khối lượng quá thấp. Tôi đã tăng âm lượng của thiết bị bằng cách sử dụng AudioManager đến mức tối đa và không thể vượt quá điều đó.Tăng âm lượng của âm thanh đã ghi

Tôi đã sử dụng MediaRecorder lần đầu tiên, nhưng vì nó có chức năng giới hạn và cung cấp âm thanh nén, tôi đã thử với AudioRecorder. Tôi vẫn chưa tìm ra cách để tăng âm thanh. Tôi đã kiểm tra trên các dự án trên Github quá, nhưng nó không sử dụng. Tôi đã tìm kiếm trên stackoverflow cho hai tuần qua, nhưng không thể tìm thấy bất cứ điều gì cả.

Tôi khá chắc chắn rằng điều đó là có thể, vì nhiều ứng dụng khác đang thực hiện. Ví dụ ghi âm cuộc gọi tự động làm điều đó.

Tôi hiểu rằng tôi phải làm điều gì đó với bộ đệm âm thanh, nhưng tôi không hoàn toàn chắc chắn những gì cần phải được thực hiện trên đó. Bạn có thể hướng dẫn tôi về điều đó không.

Cập nhật: -
Tôi xin lỗi vì tôi quên đề cập đến việc tôi đã sử dụng Gain. Mã của tôi gần như tương tự như RehearsalAssistant (trên thực tế tôi bắt nguồn từ đó). Việc đạt được không làm việc cho hơn 10dB và điều đó không làm tăng âm lượng âm thanh quá nhiều. Những gì tôi muốn là tôi sẽ có thể nghe âm thanh mà không đặt tai của tôi trên loa đó là những gì thiếu trong mã của tôi.

Tôi đã hỏi một câu hỏi tương tự về hoạt động của âm lượng/độ ồn tại SoundDesign SE here. Nó đề cập rằng Gain và loudness có liên quan nhưng nó không thiết lập mức độ ồn thực tế. Tôi không chắc chắn mọi thứ hoạt động như thế nào, nhưng tôi quyết tâm đạt được sản lượng âm lượng lớn.

Trả lời

12

Bạn rõ ràng có công cụ AudioRecord đang chạy, vì vậy, tôi bỏ qua quyết định cho sampleRateinputSource. Điểm chính là bạn cần thao tác thích hợp từng mẫu dữ liệu được ghi lại trong vòng ghi của bạn để tăng âm lượng. Giống như vậy:

int minRecBufBytes = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); 
    // ... 
    audioRecord = new AudioRecord(inputSource, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, minRecBufBytes); 

    // Setup the recording buffer, size, and pointer (in this case quadruple buffering) 
    int recBufferByteSize = minRecBufBytes*2; 
    byte[] recBuffer = new byte[recBufferByteSize]; 
    int frameByteSize = minRecBufBytes/2; 
    int sampleBytes = frameByteSize; 
    int recBufferBytePtr = 0; 

    audioRecord.startRecording(); 

    // Do the following in the loop you prefer, e.g. 
    while (continueRecording) { 
     int reallySampledBytes = audioRecord.read(recBuffer, recBufferBytePtr, sampleBytes); 

     int i = 0; 
     while (i < reallySampledBytes) { 
      float sample = (float)(recBuffer[recBufferBytePtr+i ] & 0xFF 
            | recBuffer[recBufferBytePtr+i+1] << 8); 

      // THIS is the point were the work is done: 
      // Increase level by about 6dB: 
      sample *= 2; 
      // Or increase level by 20dB: 
      // sample *= 10; 
      // Or if you prefer any dB value, then calculate the gain factor outside the loop 
      // float gainFactor = (float)Math.pow(10., dB/20.); // dB to gain factor 
      // sample *= gainFactor; 

      // Avoid 16-bit-integer overflow when writing back the manipulated data: 
      if (sample >= 32767f) { 
       recBuffer[recBufferBytePtr+i ] = (byte)0xFF; 
       recBuffer[recBufferBytePtr+i+1] =  0x7F; 
      } else if (sample <= -32768f) { 
       recBuffer[recBufferBytePtr+i ] =  0x00; 
       recBuffer[recBufferBytePtr+i+1] = (byte)0x80; 
      } else { 
       int s = (int)(0.5f + sample); // Here, dithering would be more appropriate 
       recBuffer[recBufferBytePtr+i ] = (byte)(s & 0xFF); 
       recBuffer[recBufferBytePtr+i+1] = (byte)(s >> 8 & 0xFF); 
      } 
      i += 2; 
     } 

     // Do other stuff like saving the part of buffer to a file 
     // if (reallySampledBytes > 0) { ... save recBuffer+recBufferBytePtr, length: reallySampledBytes 

     // Then move the recording pointer to the next position in the recording buffer 
     recBufferBytePtr += reallySampledBytes; 

     // Wrap around at the end of the recording buffer, e.g. like so: 
     if (recBufferBytePtr >= recBufferByteSize) { 
      recBufferBytePtr = 0; 
      sampleBytes = frameByteSize; 
     } else { 
      sampleBytes = recBufferByteSize - recBufferBytePtr; 
      if (sampleBytes > frameByteSize) 
       sampleBytes = frameByteSize; 
     } 
    } 
+0

Thực ra tôi đã sử dụng Gain, nhưng nó không hoạt động để tăng hơn 10dB. Tôi đang sử dụng mã từ URL này - http://sourceforge.net/p/rehearsalassist/code/HEAD/tree/android/branches/pause_and_gain/src/urbanstew/RehearsalAssistant/RehearsalAudioRecorder.java – noob

+0

Vui lòng kiểm tra thông tin cập nhật về câu hỏi quá. Cảm ơn. – noob

+0

Bạn nói nó không hoạt động trên 10dB? Chính xác những gì bạn quan sát lúc nói 12 hoặc 20dB? –

0

sử dụng đơn giản định dạng MPEG_4

Để tăng khối lượng ghi âm cuộc gọi AudioManager sử dụng như sau:

int deviceCallVol; 
AudioManager audioManager; 

Start Recording:

audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); 
//get the current volume set 
deviceCallVol = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); 
//set volume to maximum 
     audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0); 

    recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL); 
    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); 
    recorder.setAudioEncodingBitRate(32); 
    recorder.setAudioSamplingRate(44100); 

Stop Recording:

// trở lại thể tích trạng thái ban đầu

audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, deviceCallVol, 0); 
+0

Cảm ơn câu trả lời. Tôi đã thử nhiều định dạng khác nhau. MediaRecorder chắc chắn không giải quyết được mục đích của tôi (Trừ khi có hack hoặc làm việc xung quanh). Tôi đang mong đợi một số loại thuật toán có thể được áp dụng cho bộ đệm âm thanh để cải thiện độ ồn. – noob

+0

Cảm ơn câu trả lời này. Tôi đã có vấn đề tương tự, và thay đổi MPEG_4/AAC từ 3GPP/AMR_NB cải thiện chất lượng và khối lượng đáng chú ý. – tpaczesny

1

Trong ứng dụng của tôi, tôi sử dụng mã nguồn mở sonic library. Mục đích chính của nó là để tăng tốc độ/làm chậm lời nói, nhưng bên cạnh đó nó cho phép tăng độ ồn quá. Tôi áp dụng nó để phát lại, nhưng nó phải làm việc để ghi âm tương tự. Chỉ cần vượt qua mẫu của bạn thông qua nó trước khi nén chúng. Nó cũng có giao diện Java. Hi vọng điêu nay co ich.

+0

Cảm ơn, tôi sẽ kiểm tra. – noob

2

Nhờ Hartmut và beworker cho giải pháp. Mã của Hartmut đã hoạt động ở mức 12-14 dB. Tôi đã hợp nhất mã từ thư viện âm thanh để tăng âm lượng, nhưng điều đó làm tăng quá nhiều tiếng ồn và biến dạng, vì vậy tôi đã giữ âm lượng ở mức 1,5-2,0 và thay vào đó đã cố gắng tăng mức tăng. Tôi có âm lượng khá lớn, âm thanh không quá lớn trong điện thoại, nhưng khi nghe trên PC đủ to. Có vẻ như đó là quãng đường xa nhất mà tôi có thể đi.

Tôi đang đăng mã cuối cùng của mình để tăng độ ồn. Lưu ý rằng việc sử dụng mVolume tăng làm tăng quá nhiều tiếng ồn. Thay vào đó, hãy thử tăng thu nhập.

private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener() { 
     @Override 
     public void onPeriodicNotification(AudioRecord recorder) { 
      aRecorder.read(bBuffer, bBuffer.capacity()); // Fill buffer 
      if (getState() != State.RECORDING) 
       return; 
      try { 
       if (bSamples == 16) { 
        shBuffer.rewind(); 
        int bLength = shBuffer.capacity(); // Faster than accessing buffer.capacity each time 
        for (int i = 0; i < bLength; i++) { // 16bit sample size 
         short curSample = (short) (shBuffer.get(i) * gain); 
         if (curSample > cAmplitude) { // Check amplitude 
          cAmplitude = curSample; 
         } 
         if(mVolume != 1.0f) { 
          // Adjust output volume. 
          int fixedPointVolume = (int)(mVolume*4096.0f); 
          int value = (curSample*fixedPointVolume) >> 12; 
          if(value > 32767) { 
           value = 32767; 
          } else if(value < -32767) { 
           value = -32767; 
          } 
          curSample = (short)value; 
          /*scaleSamples(outputBuffer, originalNumOutputSamples, numOutputSamples - originalNumOutputSamples, 
            mVolume, nChannels);*/ 
         } 
         shBuffer.put(curSample); 
        } 
       } else { // 8bit sample size 
        int bLength = bBuffer.capacity(); // Faster than accessing buffer.capacity each time 
        bBuffer.rewind(); 
        for (int i = 0; i < bLength; i++) { 
         byte curSample = (byte) (bBuffer.get(i) * gain); 
         if (curSample > cAmplitude) { // Check amplitude 
          cAmplitude = curSample; 
         } 
         bBuffer.put(curSample); 
        } 
       } 
       bBuffer.rewind(); 
       fChannel.write(bBuffer); // Write buffer to file 
       payloadSize += bBuffer.capacity(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       Log.e(NoobAudioRecorder.class.getName(), "Error occured in updateListener, recording is aborted"); 
       stop(); 
      } 
     } 

     @Override 
     public void onMarkerReached(AudioRecord recorder) { 
      // NOT USED 
     } 
    }; 
Các vấn đề liên quan