package gti310.lab02.audio;
/******************************************************
Cours : GTI310
Session : automne 2009
Groupe : 01
Projet : Laboratoire 2
etudiant(e)(s) : Guillaume Grasset
Alix Beltchika
Code(s) perm. : GRAG04048102
BELM16537500
Charge de cours : Olivier Clment
Charge de laboratoire : Jean-Franois Franche
Date cree : 2009-09-20
*******************************************************/
import gti310.lab02.tools.ByteConverter;
import java.io.IOException;
public class WAVFrequenceAudioFilter implements AudioFilter {
private static final int BLOC_SIZE = 1000;
private static final int NEW_FREQUENCE = 8000;
private static final int INIT_FREQUENCE = 44100;
private static final double INTERPOLATION_SIZE = (double) INIT_FREQUENCE / (double) NEW_FREQUENCE;
private WAVDataReader wavReader;
private WAVDataWriter wavWriter;
private String inputFileLocation;
private String outputFileLocation;
public WAVFrequenceAudioFilter(String inputFileLocation, String outputFileLocation) {
this.inputFileLocation = inputFileLocation;
this.outputFileLocation = outputFileLocation;
}
@Override
public void process() {
// lecture du fichier d'entre
try {
System.out.println("Dmarrage du traitement...");
wavReader = new WAVDataReader(inputFileLocation);
// verification de la validit du fichier
if (!(wavReader.isValid()) || wavReader.getFrequence() != INIT_FREQUENCE)
throw new IOException();
// calcul de la nouvelle taille du fichier
long initDataSize = wavReader.getDataSize();
int newSize = (int) (initDataSize * ((double) NEW_FREQUENCE / (double) INIT_FREQUENCE));
// ouverture du nouveau fichier
wavWriter = new WAVDataWriter(outputFileLocation, wavReader.getMetaDataBlock(), NEW_FREQUENCE, newSize, wavReader.getBytePerBloc());
byte[] data = null;
int nbBloc = (int) (initDataSize / BLOC_SIZE) + 1;
System.out.println("Traitement en cours : ");
// traitement bloc par bloc du fichier
for (int i = 1; i <= nbBloc; i++) {
// lecture d'un bloc
data = wavReader.getData(BLOC_SIZE);
// traitement du bloc
data = processData(data, wavReader.getNbrCanaux(), wavReader.getEchantillonnage());
// ecriture du bloc trait
wavWriter.setData(data);
// affichage de l'avancement
if (nbBloc > 20 && i % (int) ((double) nbBloc / 20.) == 0)
System.out.println("\t" + (int) (((double) i / (double) nbBloc) * (double) 100) + "%");
}
System.out.println("\t100%");
System.out.println("\nTraitement termin !");
} catch (IOException e) {
System.err.println("Error : invalide File !");
//e.printStackTrace();
}
}
private byte[] processData(byte[] inputData, int nbrCanaux, int echantionnage) {
boolean isStereo = (wavReader.getNbrCanaux() == 2);
boolean is16bits = (wavReader.getEchantillonnage() == 16);
int inputDataCount = 0, doubleTmpCount = 0, outputDataCount = 0;
int interpolationCount = (int) Math.floor(INTERPOLATION_SIZE);
byte[] canal1ByteTmp = new byte[2];
double[] canal1DoubleTmp = new double[(int) interpolationCount];
byte[] canal2ByteTmp = new byte[2];
int[] canal2IntTmp = new int[(int) interpolationCount];
byte[] outputData = new byte[(int) (inputData.length / interpolationCount)];
// si on a deux canaux, on traite un data sur deux
// sinon on traite les data a la suite
// si on est en 16 bit (ranging from -32768 to 32767)
// sinon on est en 8 bit(ranging from 0 to 255)
// on parcourt les donnes
while (inputDataCount < inputData.length) {
// pour le premier canal
canal1ByteTmp[0] = inputData[inputDataCount];
inputDataCount++;
if (is16bits) {
canal1ByteTmp[1] = inputData[inputDataCount];
inputDataCount++;
canal1DoubleTmp[doubleTmpCount] = ByteConverter.byteArrayToSignedInt(canal1ByteTmp);
} else {
canal1DoubleTmp[doubleTmpCount] = ByteConverter.byteToUnsignedInt(canal1ByteTmp[0]);
}
// pour le deuxieme canal
if (isStereo) {
canal2ByteTmp[0] = inputData[inputDataCount];
inputDataCount++;
if (is16bits) {
canal2ByteTmp[1] = inputData[inputDataCount];
inputDataCount++;
canal2IntTmp[doubleTmpCount] = ByteConverter.byteArrayToSignedInt(canal2ByteTmp);
} else {
canal2IntTmp[doubleTmpCount] = ByteConverter.byteToUnsignedInt(canal2ByteTmp[0]);
}
}
doubleTmpCount++;
// lorsque l'on a assez de donnes dans le tableau, on les traites
if ((doubleTmpCount % interpolationCount) == 0) {
double valeurSortie;
// Pour le premier canal
// on interpole
valeurSortie = interpolationMultiple(canal1DoubleTmp);
// si on est sur 16 bits on sort 2 octets
if (is16bits) {
// on converti la valeur en octet
byte[] byteTmp = ByteConverter.signedIntTo16bitsByteArray((short) valeurSortie);
outputData[outputDataCount] = byteTmp[0];
outputDataCount++;
outputData[outputDataCount] = byteTmp[1];
} else { // sinon un seul
outputData[outputDataCount] = ByteConverter.unsignedIntTo8bitsByte((short) valeurSortie);
}
outputDataCount++;
// si on est en stro, on recommence pour le second canal
if (isStereo) {
valeurSortie = interpolationMultiple(canal1DoubleTmp);
// si on est sur 16 bits on sort 2 octets
if (is16bits) {
// on converti la valeur en octet
byte[] byteTmp = ByteConverter.signedIntTo16bitsByteArray((short) valeurSortie);
outputData[outputDataCount] = byteTmp[0];
outputDataCount++;
outputData[outputDataCount] = byteTmp[1];
} else { // sinon un seul
outputData[outputDataCount] = ByteConverter.unsignedIntTo8bitsByte((short) valeurSortie);
}
outputDataCount++;
}
// on rinitialise le compteur de d'interpolation
doubleTmpCount = 0;
}
}
// on retourne les donnes
return outputData;
}
/*
private double interpolationMultiple(double[] doubleTmp) {
return ((doubleTmp[0]+doubleTmp[1]+doubleTmp[2]+doubleTmp[3]+doubleTmp[4])/5.);
}
*/
private double interpolationMultiple(double[] doubleTmp) {
if (doubleTmp.length > 1) {
double[] doubleTmp2 = new double[doubleTmp.length - 1];
for (int i = 0; i < (doubleTmp.length - 1); i++)
doubleTmp2[i] = interpolationSimple(doubleTmp[i], doubleTmp[i + 1]);
return interpolationMultiple(doubleTmp2);
}
return doubleTmp[0];
}
private double interpolationSimple(double int1, double int2) {
return ((int1 + int2) / 2.);
}
}
|