JavascriptProva

Visualizzazione post con etichetta audio. Mostra tutti i post
Visualizzazione post con etichetta audio. Mostra tutti i post

lunedì 14 marzo 2016

audioRecorder, primi rudimenti.

Mi preparo tutte le impostazioni relative al tipo di segnale digitale, e dichiaro la variabile per l'audioRecorder e per il Thread (è ovvio che la registrazione va su un thread separato altrimenti si impappa tutto),
Poi ho due metodi: startRecording, che istanzia un audioRecorder e lo avvia sul thread suo leggendo i dati che arrivano dal microfono (o altra fonte) nel buffer; e stopRecording che stoppa il loop della registrazione, ferma l'audioRecorder e me lo distrugge.

Ecco le dichiarazioni:
 private Thread recordingThread=null;
 boolean isRecording;
 Button button1;
 
 int audioSource=AudioSource.MIC;
 int sampleRate=8000;
 int channelConfig=AudioFormat.CHANNEL_IN_MONO;
 int audioFormat=AudioFormat.ENCODING_PCM_16BIT;
 int bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
 AudioRecord audioRecord;
 byte[] buffer=new byte[bufferSizeInBytes];
E il codice che attribuisce il listener al bottone che avvia e stoppa la registrazione:
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  button1=(Button)findViewById(R.id.button1);
  button1.setOnClickListener(new View.OnClickListener() {
   
   @Override
   public void onClick(View v) {
    if(isRecording){
     ((Button)v).setText("Stop recording");
     stopRecording();
    }
    else{
     ((Button)v).setText("Start recording");
     startRecording();
    }
    
    
   }
  });


Poi il codice che crea e quello che distrugge l'audioRecorder:
La prima funzione è startRecording:
 public void startRecording(){
  isRecording=true;
  audioRecord=new AudioRecord(audioSource,sampleRate,channelConfig,audioFormat,bufferSizeInBytes);
  recordingThread=new Thread(new Runnable(){

   @Override
   public void run() {
    while(isRecording){
     audioRecord.read(buffer,0,bufferSizeInBytes);
    }
    
   }
   
  });
  
 }


E l'altra è stopRecording:
 public void stopRecording(){
  isRecording=false;
  audioRecord.stop();
  audioRecord.release();
  audioRecord=null; 
 }
E pare che funzioni.
Ovviamente non lo posso testare perché mi manca ancora uno strumento con funzioni di player...
Comunque perlomeno non si blocca, ed è già qualcosa.

domenica 13 marzo 2016

AudioRecorder: primi passi.

Apro Eclipse.
Devo creare un audioRecord.
Per farlo, riprendo il codice che avevo messo sul blog...

Per creare un audioRecord dovevo definire alcuni parametri:
  1. Source (microfono);
  2. Sample Rate;
  3. Channel configuration (sarebbe STEREO o MONO);
  4. AudioFormat (sarebbe la quantità di bit di cui è fatto il segnale)
  5. la lunghezza del buffer, che si ricava dai tre parametri precedenti.
Ci provo: inizio scrivendo solo i nomi delle variabili, di tipo int:
public class MainActivity extends Activity{

 int audioSource;
 int sampleRate;
 int channelConfig;
 int audioFormat;
 int bufferSizeInBytes;
 
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  
 }
  
}
Adesso calcolo queste variabili con le rispettive funzioni.
 int audioSource=AudioSource.MIC;
 int sampleRate=8000;
 int channelConfig=AudioFormat.CHANNEL_IN_MONO;
 int audioFormat=AudioFormat.ENCODING_PCM_16BIT;
 int bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
Bene.
Adesso cancello tutto e ci vado a memoria, senza sbirciare...

 int audioSource=AudioSource.MIC;
 int sampleRate=8000;
 int channelConfig=AudioFormat.CHANNEL_IN_MONO;
 int audioFormat=AudioFormat.ENCODING_PCM_16BIT;
 int bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRate,channelConfig,audioFormat);
Perfetto!!!
Ora dovrei creare l'audioRecorder...

La sintassi sembra la solita, con tutti questi valori come parametri.
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  AudioRecord audioRecord = new AudioRecord(audioSource,sampleRate, channelConfig, audioFormat, bufferSizeInBytes);
Adesso cosa fare?

ho visto che bisognava anche definire un buffer, di tipo short.
La sintassi che ho trovato su un sito era questa:
short[] buffer = new short[bufferSizeInBytes];
Su un altro sito trovo questa sintassi:
buffer = new short[buffersizebytes]; 
buflen=buffersizebytes/2; 
Quel buflen sarebbe la lunghezza in short, essendo il tipo short di 16 bytes...
Quindi una volta creato il recorder bisogna vedere come scrive sul buffer.
Confronto le sintassi:
audioRecord.startRecording(); 
mSamplesRead = audioRecord.read(buffer, 0, buffersizebytes); 
audioRecord.stop(); 
Ecco, la funzione sarebbe read.

Perché sia racchiusa fra startRecording e stop, lo ignoro...
Vediamo...

Niente, la sintassi è questa.
Provo a metterla in atto.
public class MainActivity extends Activity{

 int audioSource=AudioSource.MIC;
 int sampleRate=8000;
 int channelConfig=AudioFormat.CHANNEL_IN_MONO;
 int audioFormat=AudioFormat.ENCODING_PCM_16BIT;
 int bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRate,channelConfig,audioFormat);
 
 short[] buffer=new short[bufferSizeInBytes];
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  AudioRecord audioRecord = new AudioRecord(audioSource,sampleRate, channelConfig, audioFormat, bufferSizeInBytes);
  audioRecord.startRecording();
  audioRecord.read(buffer, 0, bufferSizeInBytes);
    
    
 }
}
E fin qua dovremmo esserci... Non so che farci, con questo buffer, ammesso che si riempia, ma comunque dovremmo esserci.
Mi aspetto che se avvio il codice succederà una catastrofe...

Ripasso di elementi di audio digitale

Quanti parametri ha AudioRecord?
Il primo parametro è audiosource: cosa è?
Era come quella che avevo visto per MediaRecorder: la sorgente audio.
Potrei scegliere "Microfono"...
AudioRecord audioRecord=new AudioRecord(MediaRecorder.AudioSource.MIC,)

Il secondo parametro è sampleRateInHz: il nome spiega che sarebbe la frequenza di campionamento.
Il valore più usato sarebbe 44100.

Il terzo è channelConfig che sarebbe la differenza fra MONO, STEREO.

Il quarto è audioFormat che può essere 8 bit, 16 bit o float (quest'ultimo non l'ho mai sentito)

Il quinto e ultimo parametro è bufferSizeInBytes, che a quanto ho capito può essere determinato nel suo valore ottimale mediante un'altra funzione, che sarebbe getMinBufferSize la quale troverebbe il valore minimo del buffer necessario per lavorare con certi parametri.



E non vogliamo andare a vedercela subito, questa funzione getMinBufferSize?
Ecco qui un pezzo di codice preso da StackOverflow dove viene definita la lunghezza del buffer per mezzo di questa funzione:
int audioSource = AudioSource.MIC;
int sampleRateInHz = 8000;
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
Questa funzione usa Sample Rate, Channel Config e Audio Format per derivare la minima dimensione necessaria per il buffer.
Cioè, per intendermi, usa cose piuttosto semplici da capire:
  • La frequenza di campionamento
  • il fatto che si voglia registrare un suono STEREO o MONO
  • il formato a 8 o 16 bit

E ora mi sento un po' più tranquillo sulla cosa...