2014-09-28 11 views
7

Sto provando a creare un'app di registrazione delle chiamate su Android. Sto usando l'altoparlante per registrare sia l'audio in uplink che in downlink. L'unico problema che sto affrontando è che il volume è troppo basso. Ho aumentato il volume del dispositivo usando AudioManager al massimo e non posso andare oltre.Aumenta l'uscita del volume dell'audio registrato

Ho usato MediaRecorder per la prima volta, ma poiché ha funzioni limitate e fornisce audio compresso, ho provato con AudioRecorder. Ancora non ho capito come aumentare l'audio. Ho controllato anche progetti su Github, ma è inutile. Ho cercato su StackOverflow per le ultime due settimane, ma non ho trovato nulla.

Sono sicuro che è possibile, dal momento che molte altre app lo stanno facendo. Ad esempio, il registratore automatico delle chiamate lo fa.

Capisco che devo fare qualcosa con il buffer audio, ma non sono abbastanza sicuro di cosa si debba fare. Puoi guidarmi su questo.

Aggiornamento: -
mi dispiace che ho dimenticato di dire che sto già usando Gain. Il mio codice è quasi simile a RehearsalAssistant (in effetti l'ho derivato da lì). Il guadagno non funziona per più di 10 dB e ciò non aumenta troppo il volume dell'audio. Quello che volevo è che dovrei essere in grado di ascoltare l'audio senza mettere l'orecchio sull'altoparlante, che è quello che manca nel mio codice.

Ho posto una domanda simile sul funzionamento del volume/volume di SoundDesign SE here. Indica che il guadagno e il volume sono correlati ma non imposta il livello di volume effettivo. Non sono sicuro di come funzionano le cose, ma sono determinato a ottenere un volume elevato.

risposta

12

È, ovviamente, hanno la roba AudioRecord corsa, così ho saltare la decisione per sampleRate e inputSource. Il punto principale è che è necessario manipolare appropriatamente ciascun campione dei dati registrati nel loop di registrazione per aumentare il volume. In questo modo:

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

In realtà sto già utilizzando il guadagno, ma non funziona per più di 10dB di aumento. Sto usando il codice da questo URL - http://sourceforge.net/p/rehearsalassist/code/HEAD/tree/android/branches/pause_and_gain/src/urbanstew/RehearsalAssistant/RehearsalAudioRecorder.java – noob

+0

Si prega di controllare le informazioni aggiornate sulla domanda pure. Grazie. – noob

+0

Hai detto che non funziona per più di 10dB? Che cosa osservi esattamente a 12 o 20 dB? –

0

uso semplice formato MPEG_4

Per aumentare il volume di registrazione delle chiamate uso AudioManager come segue:

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:

// tornare volume allo stato iniziale

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

Grazie per la risposta. Ho già provato vari formati. MediaRecorder sicuramente non risolve il mio scopo (Tranne se c'è un trucco o un lavoro in giro). Mi sto aspettando un qualche tipo di algoritmo che può essere applicato al buffer audio per migliorare il volume. – noob

+0

Grazie per questa risposta. Ho riscontrato problemi simili e il passaggio da MPEG_4/AAC a 3GPP/AMR_NB ha migliorato notevolmente la qualità e il volume. – tpaczesny

1

Nella mia app che uso un open source sonic library. Il suo scopo principale è quello di accelerare/rallentare il parlato, ma oltre a ciò consente anche di aumentare il volume. Lo applico per la riproduzione, ma deve funzionare per la registrazione in modo simile. Passa semplicemente i tuoi campioni attraverso di esso prima di comprimerli. Ha anche un'interfaccia Java. Spero che questo ti aiuti.

+0

Grazie, lo controllerò. – noob

2

Grazie a Hartmut e beworker per la soluzione. Il codice di Hartmut ha funzionato a circa 12-14 dB. Ho anche unito il codice della libreria sonora per aumentare il volume, ma aumentando troppo il rumore e la distorsione, quindi ho mantenuto il volume a 1.5-2.0 e invece ho cercato di aumentare il guadagno. Ho ottenuto un volume sonoro decente che non suona troppo forte nel telefono, ma quando ascoltato su un PC suona abbastanza forte. Sembra che sia il più lontano possibile.

Sto postando il mio codice finale per aumentare il volume. Essere consapevoli del fatto che l'utilizzo di mVolume aumenta eccessivamente il rumore. Cerca invece di aumentare il guadagno.

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 
     } 
    }; 
Problemi correlati