PDM Avanzado Captura de Audio

De MediaWiki
Ir a la navegación Ir a la búsqueda

Introducion

Con esta clase podemos capturar audio ou vídeo.


Nesta sección imos aprender como capturar audio dende Android.
Se queredes saber como capturar vídeo accedendo ao hardware (a cámara) directamente, tedes que seguir a guía de Android onde se explica os pasos a seguir.
Lembrar que podemos facer a captura moito máis facilmente chamando cun Intent a aplicación da cámara do S.O. como veremos na seguinte sección da Wiki.



A clase que imos utilizar é a Clase MediaRecorder.

Podedes ver os formatos de audio soportados en: http://developer.android.com/guide/appendix/media-formats.html

Nota: Poderíamos usar a clase AudioRecord pero como non imos procesar e analizar o audio capturado e polo tanto non a usaremos.


Para facelo necesitaremos engadir unha serie de permisos ao arquivo AndroidManifiest.xml.

  • Permiso para capturar audio.
1     <uses-permission android:name="android.permission.RECORD_AUDIO"/>


  • Permiso para gardar o audio capturado na tarxeta SD.
1     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


IMPORTANTE: A partires da API 23 (Android 6), Android incorpora outro nivel de seguridade, de tal forma que agora, a maiores, teremos que solicitar dito permiso a nivel de programación. Máis información de como facelo neste enlace.

Clase MediaRecorder

Os pasos que temos que dar para capturar audio son os seguintes:

  • Crear un obxecto da clase MediaRecorder.
1  private MediaRecorder mediaRecorder;
2  ...........
3  mediaRecorder = new MediaRecorder();
  • Establecer de onde vén a fonte de audio. O normal é que sexa do MIC da cámara web. Isto se fai chamando ó método setAudioSource(fonte) onde fonte é unha constante que atopades en MediaRecorder.AudioSource.XXXXX.
1 mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
  • Establecer o formato de saída, chamando ó método setOutputFormat(formato) onde formato é unha constante que se atopa en MediaRecorder.OutputFormat.XXX
1 mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
PDM Avanzada Multimedia Reprod 10.jpg
Imaxe obtida de http://developer.android.com/guide/appendix/media-formats.html

A columna de Supported File Type indica o formato de saída. No noso caso usaremos MediaRecorder.OutputFormat.TREE_GPP.


  • Optativo: Establecer o tempo máximo de gravación chamando o método setMaxDuration(int mseg) do obxecto MediaRecorder.

Nos imos poñer 10000 (10 segundos).

1 mediaRecorder.setMaxDuration(10000);
  • Optativo: Indicar a tasa de bit´s, chamando ó método setAudioEncodingBitRate(int valor).

Os permitidos o tedes no na imaxe anterior.

Nota: A cantidade de bit´s vai establecer a calidade do audio capturado.

Algúns valores típicos:

  • Tasas de bits de compresión a MP3:
4 kbit/s Mínimo para recoñecer a fala.
8 kbit/s Calidade telefónica convencional
32 kbit/s Radio AM
96 kbit/s Radio FM
128 kbit/s Son calidade semi CD, muy común en MP3
192 kbit/s Son calidade CD en formato MP3
320 kbit/s Máxima calidade para formato MP3

Nos imos probar con 32 * 1024 = 32768

1 mediaRecorder.setAudioEncodingBitRate(32768);
  • Optativo: Indicar a frecuencia de muestreo, chamando ó método setAudioSamplingRate(int valor).

ATENCION: No emulador este valor non pode ser superior a 8000.

PDM Avanzada Multimedia Reprod 11.jpg

Máis información: http://es.wikipedia.org/wiki/Frecuencia_de_muestreo

Un exemplo, no caso de calidade CD o simplerate é de 44,1Khz. No noso caso o valor estará limitado pola táboa de formatos de audio. Por exemplo AAC está limitado entre 8Khz e 96Khz, AMR_NB só a 8Khz e AMR_WB a 16Khz.

Nos imos probar con 8000 (8Khz) pola limitación do emulador.

1 mediaRecorder.setAudioSamplingRate(8000); // No emulador só 8000


  • Indicar a codificación de audio utilizada chamando ó método setAudioEncoder(método) onde método é unha constante que se atopa en MediaRecorder.AudioEncoder.XXX.

No noso caso imos utilizar MediaRecorder.AudioEncoder.AAC.

1 mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
  • Indicar o arquivo a gravar, indicando a ruta nome e extensión do arquivo, chamando ó método setOutputFile(arquivogravar).

Aquí temos varias posibilidades. Unha delas é darlle coma valor un String no que vai a ruta e o nome de arquivo e extensión. A ruta será algún cartafol da SDCARD. Para obter esa ruta faremos uso da clase Environment.

Para saber onde gardar o arquivo tedes que facer uso da clase Environment: http://developer.android.com/reference/android/os/Environment.html

Exemplos:

1 Environment.getExternalStorageDirectory().getAbsolutePath()
Con isto obtemos a ruta a SDCARD (raíz).
1 String state = Environment.getExternalStorageState(); 
2 if(!state.equals(Environment.MEDIA_MOUNTED)){
3 // A TARXETA NON ESTA MONTADA
4 }
Con isto sabemos se a tarxeta SD está montada.


Nota: Tamén podemos crear a ruta na SDCARD, facendo uso de obxectos da clase File, ou comprobando se existe o cartafol. O veremos máis adiante.

1 private String arquivoGravar;
2 ................
3 String timeStamp = DateFormat.getDateTimeInstance().format(new Date()).replaceAll(":", "").replaceAll("/", "_")	.replaceAll(" ", "_");
4 
5 arquivoGravar = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + timeStamp + ".3gp";
6 
7 mediaRecorder.setOutputFile(arquivoGravar);

Neste exemplo creamos un nome para o arquivo gravado baseado na data-hora e o vai gardar no cartafol da SD Externa que o S.O. reserva para gardar música.


  • Chamar ó método prepare(). Pode producir excepcións (debe ir con try...catch).
1 mediaRecorder.prepare();


  • Chamar ó método start().
1 mediaRecorder.start();


Neste intre se procede a gravar no cartafol indicado. A gravación non parará ata que chamemos ó método stop do MediaRecorder ou se acade o tempo máximo de gravación.


É importante seguir a orden, xa que por exemplo, a chamada a setAudioEncoder non pode ir antes de setOutputFormat (mirade o diagrama de estados seguinte). Ó igual que o MediaPlayer, o MediaRecorder ten un diagrama de estados que xa non debería ter dificultade en entenderse:

PDM Avanzada Multimedia Reprod 12.jpg
Imaxe obtido de http://developer.android.com/reference/android/media/MediaRecorder.html


Cando rematemos de gravar (por tempo) ou se paramos nos premendo o botón correspondente se recomenda liberar os recursos do MediaRecorder.

O faremos así:

  • Chamando o método stop.
  • Chamando o método release.
  • Igualando a null o obxecto da clase MediaRecorder.

Tamén deberemos liberar os recursos se cambiamos de aplicación ou se a pechamos.

Caso práctico

O obxectivo desta práctica é gravar un arquivo de audio no cartafol da SD Externa reservado á música. Ó premer o botón Gravar amosaremos unha caixa de diálogo indicando que se está a gravar e o saír de dita caixa pararemos de gravar. Ó premer o botón Reproducir reproduciremos o arquivo gardado.

PDM Avanzada Multimedia Reprod 13.jpg

Creamos a Activity

  • Nome do proxecto: UD6_03_MultimediaGravador
  • Nome da activity: UD6_03_MultimediaGravador.java


Código do layout xml
Nota: Por motivos de tempo para o alumnado o deseño non fai uso de constantes externas definidas no cartafol values. Queda claro que esta debería ser a opción escollida para o deseño das Interfaces de Usuario.

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context="${relativePackage}.${activityClass}" >
 6 
 7     <Button
 8         android:id="@+id/UD6_03_btnGravar"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:layout_alignParentTop="true"
12         android:layout_centerHorizontal="true"
13         android:text="GRAVAR AUDIO" />
14 
15     <Button
16         android:id="@+id/UD6_03_btnReproducir"
17         android:layout_width="wrap_content"
18         android:layout_height="wrap_content"
19         android:layout_below="@+id/UD6_03_btnGravar"
20         android:layout_centerHorizontal="true"
21         android:layout_marginTop="26dp"
22         android:text="REPRODUCIR AUDIO" />
23 </RelativeLayout>


Código da clase UD6_03_MultimediaGravador
Obxectivo: Amosar como gravar un arquivo de audio.

  1 import java.io.File;
  2 import java.text.DateFormat;
  3 import java.util.Date;
  4 
  5 import android.app.Activity;
  6 import android.app.AlertDialog;
  7 import android.content.DialogInterface;
  8 import android.media.AudioManager;
  9 import android.media.MediaPlayer;
 10 import android.media.MediaRecorder;
 11 import android.os.Bundle;
 12 import android.os.Environment;
 13 import android.view.View;
 14 import android.view.View.OnClickListener;
 15 import android.widget.Button;
 16 import android.widget.Toast;
 17 
 18 public class UD6_03_MultimediaGravador extends Activity {
 19 
 20 	private MediaRecorder mediaRecorder;
 21 	private String arquivoGravar;
 22 	
 23 	
 24 	private void abrirDialogo(String tipo){
 25 		if (tipo == "GRAVAR") {
 26 			AlertDialog.Builder dialog = new AlertDialog.Builder(this)
 27 					.setMessage("GRAVANDO").setPositiveButton(
 28 							"PREME PARA PARAR",
 29 							new DialogInterface.OnClickListener() {
 30 
 31 								@Override
 32 								public void onClick(DialogInterface dialog,
 33 										int which) {
 34 									// TODO Auto-generated method stub
 35 									mediaRecorder.stop();
 36 									mediaRecorder.release();
 37 									mediaRecorder = null;
 38 								}
 39 							});
 40 			dialog.show();
 41 		}		
 42 		
 43 		if (tipo == "REPRODUCIR") {
 44 
 45 			if ((arquivoGravar==null) | arquivoGravar=="") return;
 46 			File arquivo = new File(arquivoGravar);
 47 			if (!arquivo.exists()) return;
 48 			
 49 			final MediaPlayer mediaPlayer = new MediaPlayer();
 50 			try {
 51 				mediaPlayer.setDataSource(arquivoGravar);
 52 				mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
 53 				mediaPlayer.prepare();
 54 				mediaPlayer.start();
 55 			} catch (Exception e) {
 56 				Toast.makeText(getApplicationContext(),
 57 						"ERRO:" + e.getMessage(), Toast.LENGTH_LONG).show();
 58 			}
 59 
 60 			AlertDialog.Builder dialog = new AlertDialog.Builder(this)
 61 					.setMessage("REPRODUCINDO").setPositiveButton(
 62 							"PREME PARA PARAR",
 63 							new DialogInterface.OnClickListener() {
 64 
 65 								@Override
 66 								public void onClick(DialogInterface dialog,
 67 										int which) {
 68 									// TODO Auto-generated method stub
 69 									mediaPlayer.stop();
 70 									mediaPlayer.release();
 71 								}
 72 							});
 73 			dialog.show();
 74 
 75 		}
 76 
 77 	}
 78 	
 79 	private void xestionarEventos(){
 80 		
 81 		Button btnGravar = (Button)findViewById(R.id.UD6_03_btnGravar);
 82 		btnGravar.setOnClickListener(new OnClickListener() {
 83 			
 84 			@Override
 85 			public void onClick(View v) {
 86 				// TODO Auto-generated method stub
 87 				String timeStamp = DateFormat.getDateTimeInstance().format(
 88 						new Date()).replaceAll(":", "").replaceAll("/", "_")
 89 						.replaceAll(" ", "_");
 90 
 91 				mediaRecorder = new MediaRecorder();
 92 				arquivoGravar = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + timeStamp + ".3gp";
 93 				mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 94 				mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
 95 				mediaRecorder.setMaxDuration(10000);
 96 				mediaRecorder.setAudioEncodingBitRate(32768);
 97 				mediaRecorder.setAudioSamplingRate(8000); // No emulador só 8000 coma
 98 				mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
 99 				mediaRecorder.setOutputFile(arquivoGravar);
100 				try {
101 					mediaRecorder.prepare();
102 				} catch (Exception e) {
103 				// TODO Auto-generated catch block
104 					mediaRecorder.reset();
105 				}
106 				mediaRecorder.start();
107 				abrirDialogo("GRAVAR");
108 			
109 				
110 			}
111 		});
112 		
113 		Button btnReproducir = (Button)findViewById(R.id.UD6_03_btnReproducir);
114 		btnReproducir.setOnClickListener(new OnClickListener() {
115 			
116 			@Override
117 			public void onClick(View v) {
118 				// TODO Auto-generated method stub
119 				abrirDialogo("REPRODUCIR");
120 			}
121 		});
122 		
123 		
124 	}
125 	
126 	@Override
127 	protected void onCreate(Bundle savedInstanceState) {
128 		super.onCreate(savedInstanceState);
129 		setContentView(R.layout.activity_ud6_03__multimedia_gravador);
130 		
131 		xestionarEventos();
132 		
133 	}
134 }
  • Liña 20: Definimos o MediaRecorder.
  • Liña 21: Propiedade que garda o nome e ruta do arquivo gravado. Necesario para cando prememos o botón de reproducir.
  • Liñas 25-41: Diálogo que aparece cando prememos sobre o botón de Gravar. Se prememos o botón de Aceptar dentro do diálogo paramos de gravar e liberamos o MediaRecorder.
  • Liñas 43-75: Diálogo que aparece cando prememos sobre o botón de Reproducir. Xa visto no punto anterior desta Unidade Didáctica.
  • Liñas 91-107: Xestión do evento click sobre o botón de gravar. Preparamos o MediaRecorder e chamamos a abrir o diálogo de gravación.
  • Liñas 117-120: Xestión do evento click sobre o botón de reproducir. Abrimos o diálogo de Reproducir.




Enlace a la página principal de la UD7

Enlace a la página principal del curso



-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2014).