Autor
|
Tema: [Java Android]: Mezclador de canciones problema memoria (Leído 2,750 veces)
|
kondrag_X1
Desconectado
Mensajes: 157
|
Hola Gente , les comento. Estoy haciendo una app en android para mezclar canciones, lo más sencilla posible,es decir, canciones con misma frecuencia mismo formato 16 PCM (wav). He intentado hacer el procesamiento directo es decir coger cargar todas las canciones en memoria y hacerlo pero no es posible ya que el wav es un sistema de sonido sin perdidas y pesan muchísimo los archivos. Ahora trato de hacer un procesamiento por bloques pero no quisiera utilizar Vector, List etc ya que son objetos costosos para memoria y nivel computacional(o eso he creído leer). entonces que puedo hacer ir guardando el resultado en un archivo y después leerlo? public short[] mixFiles() { short[] output = new short[0]; try {
InputStream is1 = act.getResources().openRawResource(R.raw.mar); InputStream is2 = act.getResources().openRawResource(R.raw.musica); InputStream is3 = act.getResources().openRawResource(R.raw.aura);
InputStream inputStream = null;
//procesado por bloques byte[] bytes = null; float[] mixed = null; short[] sBuffer = null; int i = 0;
boolean read_is1 = true; boolean read_is2 = true; boolean read_is3 = true;
//leera toda la señal while( read_is1 && read_is2 && read_is3 ) { mixed = new float[1024]; //cada iteracion leera una parte de cada archivo for (int k = 0; k < 3; k++) { switch (k) { case 0: inputStream = is1; break; case 1: inputStream = is2; break; case 2: inputStream = is3; break; } try {
//leo los bytes y guardo en bytes[] bytes = new byte[1024]; new DataInputStream(inputStream).readFully(bytes, 1024*i, 1024);
//rellena el sbuffer con el formato para la reproducción. ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(sBuffer);
}catch(EOFException ex){ //si entro aqui, es porque he leido entero el fichero con valor k switch (k) { case 0: read_is1 = false; is1.close(); break; case 1: read_is2 = false; is2.close(); break; case 2: read_is3 = false; is3.close(); break; } }catch (IOException e) { //no hago nada, solo inicializo el array de bytes a 0. bytes = new byte[1024]; } //no quiero utilizar vectores ya que gastan memoria //prodria guardar la suma en dico el archivo? for (int j = 0; j < bytes.length; j++) { mixed[j] = mixed[j] + (bytes[j] / 32768.0f); // reduce the volume a bit: mixed[j] *= 0.8; // hard clipping if (mixed[j] > 1.0f) mixed[j] = 1.0f; if (mixed[j] < -1.0f) mixed[j] = -1.0f; short outputSample = (short) (mixed[j] * 32768.0f); } } pasarGarbageCollector(); mixed = null; bytes = null;
i += 1; } return output; }
|
|
|
En línea
|
|
|
|
Usuario Invitado
Desconectado
Mensajes: 625
|
1) Te recomiendo leer el libro Código limpio de R. C. Martin.
2) Acostúmbrate a hacer expresivo el código no los comentarios. Cuando un código es limpio es expresivo y fácil de entender. Coloca nombres a las variables de manera que se sepa que valores guardan.
Respecto a tu duda. puedes hacerlo de ambas formas pero por comodida y practicidad puedes hacerlo con ArrayList. No sé si estarás enterado pero en la actualidad ArrayList es una de lae colecciones más eficientes que tenemos disponibles en Java, incluso en algunas ocasiones es mucho más eficiente que arrays convencionales.
Usa ArrayList, dudo que afecte el rendimiento de tu aplicación.
PD: Disculpa si encuentras errores ortográficos, estoy en móvil.
|
|
« Última modificación: 25 Febrero 2015, 12:50 pm por Gus Garsaky »
|
En línea
|
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein
|
|
|
kondrag_X1
Desconectado
Mensajes: 157
|
muchísimas gracias la verdad es que estoy un poco desconectado de java. lo mío es c como seguramente puedes ver por el código. voy a probar con arrayList y os comento.
Esta tarde haré mas expresivo el código.
saludos y mil gracias
|
|
|
En línea
|
|
|
|
kondrag_X1
Desconectado
Mensajes: 157
|
Buenas continuo con el problema de antes, pero ahora , para mas agilidad, he portado el código a java y así depurarlo más rápido. El problema basicamente es que cuando cargo tres canciones sin comprimir de alrededor 90 megas para mezclarlas cuando guardo el resultado de la mezcla en un Array me dice: con 22838 elementos en el array. java.lang.OutOfMemoryError public static short[] mixFiles() throws FileNotFoundException {
int LEN_BUFFER = 1024; /* InputStream is1 = act.getResources().openRawResource(R.raw.mar); InputStream is2 = act.getResources().openRawResource(R.raw.musica); InputStream is3 = act.getResources().openRawResource(R.raw.aura);*/
InputStream is1 = new FileInputStream("/Users/alarcon/Desktop/Musica/musica.wav"); InputStream is2 = new FileInputStream("/Users/alarcon/Desktop/Musica/aura.wav"); InputStream is3 = new FileInputStream("/Users/alarcon/Desktop/Musica/mar.wav");
InputStream inputStream = null; ArrayList<Short> salida = new ArrayList<Short>();
//procesado por bloques byte[] samples = null; float[] samples_mixed; ByteBuffer byteBuffer; short[] samples_short = new short[LEN_BUFFER]; ShortBuffer shortBuffer; int i = 0;
boolean read_is1 = true; boolean read_is2 = true; boolean read_is3 = true;
//leera toda la señal while (read_is1 && read_is2 && read_is3) { samples_mixed = new float[LEN_BUFFER]; //cada iteracion leera una parte de cada archivo for (int k = 0; k < 3; k++) { switch (k) { case 0: inputStream = is1; break; case 1: inputStream = is2; break; case 2: inputStream = is3; break; } try {
//leo los bytes y guardo en bytes[] samples = new byte[LEN_BUFFER]; new DataInputStream(inputStream).readFully(samples, 0, LEN_BUFFER); inputStream.close();
//rellena el sbuffer con el formato para la reproducción. byteBuffer = ByteBuffer.wrap(samples).order(ByteOrder.LITTLE_ENDIAN); shortBuffer = byteBuffer.asShortBuffer(); samples_short = new short[samples.length/2]; shortBuffer.get(samples_short); System.out.println("Longitud buffer short: "+samples_short.length); }catch ( BufferUnderflowException flow){ flow.getCause(); flow.getLocalizedMessage(); flow.getStackTrace(); flow.printStackTrace(); }catch (EOFException ex) { //si entro aqui, es porque he leido entero el fichero con valor k try { switch (k) { case 0: read_is1 = false; is1.close(); break; case 1: read_is2 = false; is2.close(); break; case 2: read_is3 = false; is3.close(); break; } }catch (IOException e){} } catch (IOException e) { //no hago nada, solo inicializo el array de bytes a 0. samples_short = new short[LEN_BUFFER]; } for (int j = 0; j < samples_short.length-1; j++) { samples_mixed[j] = samples_mixed[j] + (samples_short[j] / 32768.0f); // reduce the volume a bit: samples_mixed[j] *= 0.8; // hard clipping if (samples_mixed[j] > 1.0f) samples_mixed[j] = 1.0f; if (samples_mixed[j] < -1.0f) samples_mixed[j] = -1.0f; salida.add(new Short((short) (samples_mixed[j] * 32768.0f))); } }
i += 1; System.out.println("valor i: "+i); }
Short [] aux = ((Short[]) salida.toArray()); short [] o = new short[aux.length];
for(int a = 0;a < aux.length ;a++) o[a] = aux[a].shortValue();
return o; }
siendo la línea de abajo donde me dice que se consume toda la memoria. salida.add(new Short((short) (samples_mixed[j] * 32768.0f)));
y este el error que me produce la máquina virtual de android y java. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at MezclaSonido.mixFiles(MezclaSonido.java:120) at MezclaSonido.main(MezclaSonido.java:19)
He leido que el fallo es debido a que se queda sin memoria la máquina virtual pero cuando intento de poner los parámetros en el campo run->configurations de eclipse -Xms512M -Xmx1024M ampliando así la memoria ram en la maquina virtual sigue pasando lo mismo. Alguien conoce el tema lo suficiente para echarme una mano.
|
|
|
En línea
|
|
|
|
Usuario Invitado
Desconectado
Mensajes: 625
|
A mí me parece un memory leak, aunque desconozco si el manejo de archivos multimedia grandes pueda consumir tanta RAM. Vamos a hacer un análsis de memoria. CONFIGURAR LA VM PARA VOLCADO DE MEMORIA
Luego, procedamos a hacer un volcado de memoria (dump) cuando se detecte un OutOfMemoryError: - Agrega el argumento en VM arguments:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/ruta/al/directorio/deseado Corre el programa. Cuando se produzca un OutofMemoryError, la VM hará un volcado de memoria para su posterior análisis. ANALIZANDO EL VOLCADO DE MEMORIA Instalar MAT (Memory Analyzer Tool) que Eclipse FounationPara mayor comodidad nos descargamos MAT independiente desde aquíAbrimos MAT y nos dirigimos al menú file y seleccionamos la opción Open Heap Dump. Navegas hacia la ruta donde has especificado guardar el memory dump (VM arguments en Eclipse) y seleccionas el archivo de volcado (extensión .hprof). Se nos mostrará una ventana para seleccionar la opción de análisis que deseamos. Seleccionamos la primera y le damos finish: MAT hará su trabajo y nos mostrará el análisis del memory dump. - A partir de ésta pestaña principal puedes ir muy profundo. Puedes ver como usar MAT a detalle en éste blog.
- También dispones de VisualVM, una herramienta gratuita de Java para analizar el rendimiento de aplicaciones y mucho más: http://visualvm.java.net/features.html
- Si deseas puedes establecer más RAM a tu aplicación, prueba a 2048m o si tienes 4GB de RAM 4096m. Recuerda que deben ir en VM arguments y no en Program arguments.
Saludos.
|
|
|
En línea
|
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein
|
|
|
kondrag_X1
Desconectado
Mensajes: 157
|
muchísimas gracias he probado establecer max memoria pero al ser para un dispositivo android no me interesa mucho. Te comento un poco, a ver si por fin me deshago de este pequeño marrón. ¿de la clase InputStream puedo leer byte a byte?Imagino que sí, aunque no me queda muy claro. esta sería la mas simple. do { i=inputStream.read(); }while(i != -1);
y con esta int read(byte[] b, int off, int len) b, buffer sobre el que dejaremos los bytes resultado de la lectura. off, indica la posición del buffer en la cual se almacenarán los bytes leídos. len, número de bytes a leer. ¿Siempre estoy leyendo los mismo bytes? Imagino que no cuando llegue al fin me devolverá -1 haciedno algo rápido y sin pensar mucho, abriendo 3 ficheros, de distintas longitudes. int len_file1 = input1.available(); int len_file2 = input2.available(); int len_file3 = input3.available();
short byte_file1 = 0; short byte_file2 = 0; short byte_file3 = 0; int k = 0; int suma = 0; do{ k = 0; suma = 0; if(byte_file1 = input1.readShort() >-1){ k++; suma += fin }
if(byte_file2 = input2.readShort() >-1) { k++; suma += byte_file2; //antes de sumarlas tendría que ordenarlo a little indian }
if(byte_file3 = input3.readShort() >-1) { k++; suma += byte_file3; }
//aquí para almacenarlo que seria lo mejor guardar fichero oOutputStreme? // sin gastar muca memoria }while(fin_file1 > -1 && fin_file2 > -1 && fin_file3 > -1);
|
|
« Última modificación: 26 Febrero 2015, 20:39 pm por kondrag_X1 »
|
En línea
|
|
|
|
Usuario Invitado
Desconectado
Mensajes: 625
|
Según lo que he investigado, para leer un archivo a bytes en Android, se hace así: byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = inStream.read(buffer)) > 0) { // proceso aquú } }
|
|
|
En línea
|
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
No puedo iniciar mi móvil android, memoria llena
Android
|
lnvisible
|
3
|
9,473
|
14 Septiembre 2011, 14:15 pm
por lnvisible
|
|
|
android borra informacion, spotifi las canciones
Dispositivos Móviles (PDA's, Smartphones, Tablets)
|
juanitoxx
|
1
|
3,123
|
18 Septiembre 2011, 15:27 pm
por Poderoscuro1207
|
|
|
es lo mismo Java, que Java para android?
Java
|
Belial & Grimoire
|
2
|
10,846
|
1 Enero 2012, 05:09 am
por Belial & Grimoire
|
|
|
duda liberar memoria ram android
GNU/Linux
|
General Dmitry Vergadoski
|
4
|
3,382
|
9 Febrero 2015, 19:57 pm
por el-brujo
|
|
|
Problema inicio android/recuperación memoria interna
Android
|
mrdasilva
|
0
|
2,197
|
5 Agosto 2015, 18:19 pm
por mrdasilva
|
|