2014-09-28 16 views
7

Próbuję utworzyć aplikację do nagrywania połączeń w systemie Android. Używam głośnika do nagrywania dźwięku w łączu w górę iw dół. Jedynym problemem, z jakim się borykam, jest zbyt niska głośność. Zwiększyłem głośność urządzenia za pomocą AudioManagera do maksimum i nie można go przekroczyć.Zwiększenie głośności nagranego dźwięku

Po raz pierwszy użyłem MediaRecorder, ale ponieważ miał ograniczone funkcje i zapewnia skompresowany dźwięk, próbowałem z AudioRecorder. Nadal nie mam pojęcia, jak zwiększyć dźwięk. Sprawdziłem także projekty na Githubie, ale to nie ma sensu. Szukałem na stackoverflow przez ostatnie dwa tygodnie, ale nie mogłem nic znaleźć.

Jestem pewien, że jest to możliwe, ponieważ robi to wiele innych aplikacji. Na przykład robi to nagrywarka Automatic Call.

Rozumiem, że muszę coś zrobić z buforem audio, ale nie jestem do końca pewien, co należy w tym celu zrobić. Czy możesz mnie o tym poprowadzić?

Aktualizacja: -
mi przykro, że zapomniałem wspomnieć, że jestem już za pomocą Zysk. Mój kod jest prawie podobny do RehearsalAssistant (w rzeczywistości wywnioskowałem go stąd). Wzmocnienie nie działa dla więcej niż 10 dB i nie zwiększa zbytnio głośności dźwięku. Chciałem tylko, aby móc słuchać dźwięku bez wkładania słuchawki do głośnika, czego brakuje w moim kodzie.

Zadałem podobne pytanie dotyczące funkcjonowania głośności/głośności w SoundDesign SE here. Wspomina, że ​​wzmocnienie i głośność są powiązane, ale nie określa rzeczywistego poziomu głośności. Nie jestem pewien, jak to działa, ale jestem zdeterminowany, aby uzyskać głośny sygnał wyjściowy.

Odpowiedz

12

Najwyraźniej mają rzeczy AudioRecord działa, więc pominę decyzję o sampleRate i inputSource. Najważniejsze jest to, że musisz odpowiednio manipulować każdą próbką nagranych danych w pętli nagrywania, aby zwiększyć głośność. Podobnie jak:

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

Właściwie już używam wzmocnienia, ale nie działa ono przy zwiększeniu o ponad 10dB. Używam kodu z tego adresu URL - http://sourceforge.net/p/rehearsalassist/code/HEAD/tree/android/branches/pause_and_gain/src/urbanstew/RehearsalAssistant/RehearsalAudioRecorder.java – noob

+0

Proszę sprawdzić zaktualizowane informacje na temat tego pytania także. Dzięki. – noob

+0

Mówisz, że nie działa dla więcej niż 10dB? Co dokładnie obserwujesz na poziomie 12 lub 20 dB? –

0

prosta obsługa formatu MPEG_4

Aby zwiększyć głośność nagrywania połączeń użyj Audiomanager następująco:

int deviceCallVol; 
AudioManager audioManager; 

Rozpocznij nagrywanie:

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); 

Zatrzymanie nagrywania:

// powracają objętość do stanu początkowego

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

Dzięki za odpowiedź. Próbowałem już różnych formatów. MediaRecorder zdecydowanie nie rozwiązuje mojego celu (z wyjątkiem sytuacji, gdy istnieje haker lub praca). W pewnym sensie oczekuję jakiegoś algorytmu, który można zastosować do bufora audio, aby poprawić głośność. – noob

+0

Dzięki za tę odpowiedź. Miałem podobne problemy, a zmiana MPEG_4/AAC z 3GPP/AMR_NB wyraźnie poprawiła jakość i głośność. – tpaczesny

1

W mojej aplikacji korzystam z open source sonic library. Jego głównym celem jest przyspieszenie/spowolnienie mowy, ale oprócz tego pozwala to również zwiększyć głośność. Stosuję go do odtwarzania, ale musi działać podobnie do nagrywania. Po prostu przeprowadź przez nie próbki, zanim je skompresujesz. Ma również interfejs Java. Mam nadzieję że to pomoże.

+0

Dzięki, sprawdzę to. – noob

2

Podziękowania dla Hartmuta i współpracownika za rozwiązanie. Kod Hartmuta działał na poziomie 12-14 dB. Zrobiłem też scalenie kodu z biblioteki dźwiękowej, aby zwiększyć głośność, ale to zwiększyło zbyt dużo szumów i zniekształceń, więc utrzymałem głośność na poziomie 1,5-2,0 i zamiast tego próbowałem zwiększyć wzmocnienie. Mam przyzwoitą głośność, która nie brzmi zbyt głośno w telefonie, ale kiedy słucha się na komputerze, brzmi wystarczająco głośno. Wygląda na to, że najdalej mogę się udać.

Zamieszczam mój ostatni kod, aby zwiększyć głośność. Należy pamiętać, że zwiększanie mVolume zwiększa zbyt duży hałas. Spróbuj zamiast tego zwiększyć wzmocnienie.

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 
     } 
    }; 
Powiązane problemy