Salut j'ai un fichier pcm, et je veux convertir en fichier wav. existe-t-il une API ou un code approprié pour cela?java pcm to wav
Répondre
Avez-vous regardé MP3 Encoding in Java
Cette ressource, WAVE PCM soundfile format, m'a aidé à analyser les données PCM WAVE. J'ai construit une bibliothèque basée dessus et cela fonctionne bien pour moi.
Je sais que l'un appelé « OperateWav » que je l'habitude de développer un convertisseur (linux c/C++) dans mon premier projet au cours de mes premiers internship.I ne sais pas si celui-ci existe en soi et si elle prend en charge java.Actually fichier wav est simplement l'ajout d'un en-tête de format wav sur les données brutes pcm ...
il est mon code
/**
* Write PCM data as WAV file
* @param os Stream to save file to
* @param pcmdata 8 bit PCMData
* @param srate Sample rate - 8000, 16000, etc.
* @param channel Number of channels - Mono = 1, Stereo = 2, etc..
* @param format Number of bits per sample (16 here)
* @throws IOException
*/
public void PCMtoFile(OutputStream os, short[] pcmdata, int srate, int channel, int format) throws IOException {
byte[] header = new byte[44];
byte[] data = get16BitPcm(pcmdata);
long totalDataLen = data.length + 36;
long bitrate = srate * channel * format;
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = (byte) format;
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1;
header[21] = 0;
header[22] = (byte) channel;
header[23] = 0;
header[24] = (byte) (srate & 0xff);
header[25] = (byte) ((srate >> 8) & 0xff);
header[26] = (byte) ((srate >> 16) & 0xff);
header[27] = (byte) ((srate >> 24) & 0xff);
header[28] = (byte) ((bitrate/8) & 0xff);
header[29] = (byte) (((bitrate/8) >> 8) & 0xff);
header[30] = (byte) (((bitrate/8) >> 16) & 0xff);
header[31] = (byte) (((bitrate/8) >> 24) & 0xff);
header[32] = (byte) ((channel * format)/8);
header[33] = 0;
header[34] = 16;
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (data.length & 0xff);
header[41] = (byte) ((data.length >> 8) & 0xff);
header[42] = (byte) ((data.length >> 16) & 0xff);
header[43] = (byte) ((data.length >> 24) & 0xff);
os.write(header, 0, 44);
os.write(data);
os.close();
}
EDIT: 2016-01-11
public byte[] get16BitPcm(short[] data) {
byte[] resultData = new byte[2 * data.length];
int iter = 0;
for (double sample : data) {
short maxSample = (short)((sample * Short.MAX_VALUE));
resultData[iter++] = (byte)(maxSample & 0x00ff);
resultData[iter++] = (byte)((maxSample & 0xff00) >>> 8);
}
return resultData;
}
Est-ce que 'get16BitPcm (short [])' fait juste un 'byte []' deux fois la taille de son paramètre? Si oui, quelle endianisme? Si non, que fait-il? – Scruffy
@Scruffy Oui, et désolé pour manquant, méthode., Vient de mettre à jour ma réponse. – devflow
Par http://soundfile.sapp.org/doc/WaveFormat, il semble que l'octet 16 dans l'en-tête devrait toujours être "16" pour PCM, quel que soit le nombre de bits par échantillon. – lreeder
Cela devrait être assez simple à faire parce que WAV = Métadonnées + PCM (dans cet ordre). Cela devrait fonctionner:
private void rawToWave(final File rawFile, final File waveFile) throws IOException {
byte[] rawData = new byte[(int) rawFile.length()];
DataInputStream input = null;
try {
input = new DataInputStream(new FileInputStream(rawFile));
input.read(rawData);
} finally {
if (input != null) {
input.close();
}
}
DataOutputStream output = null;
try {
output = new DataOutputStream(new FileOutputStream(waveFile));
// WAVE header
// see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
writeString(output, "RIFF"); // chunk id
writeInt(output, 36 + rawData.length); // chunk size
writeString(output, "WAVE"); // format
writeString(output, "fmt "); // subchunk 1 id
writeInt(output, 16); // subchunk 1 size
writeShort(output, (short) 1); // audio format (1 = PCM)
writeShort(output, (short) 1); // number of channels
writeInt(output, 44100); // sample rate
writeInt(output, RECORDER_SAMPLERATE * 2); // byte rate
writeShort(output, (short) 2); // block align
writeShort(output, (short) 16); // bits per sample
writeString(output, "data"); // subchunk 2 id
writeInt(output, rawData.length); // subchunk 2 size
// Audio data (conversion big endian -> little endian)
short[] shorts = new short[rawData.length/2];
ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2);
for (short s : shorts) {
bytes.putShort(s);
}
output.write(fullyReadFileToBytes(rawFile));
} finally {
if (output != null) {
output.close();
}
}
}
byte[] fullyReadFileToBytes(File f) throws IOException {
int size = (int) f.length();
byte bytes[] = new byte[size];
byte tmpBuff[] = new byte[size];
FileInputStream fis= new FileInputStream(f);
try {
int read = fis.read(bytes, 0, size);
if (read < size) {
int remain = size - read;
while (remain > 0) {
read = fis.read(tmpBuff, 0, remain);
System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
remain -= read;
}
}
} catch (IOException e){
throw e;
} finally {
fis.close();
}
return bytes;
}
private void writeInt(final DataOutputStream output, final int value) throws IOException {
output.write(value >> 0);
output.write(value >> 8);
output.write(value >> 16);
output.write(value >> 24);
}
private void writeShort(final DataOutputStream output, final short value) throws IOException {
output.write(value >> 0);
output.write(value >> 8);
}
private void writeString(final DataOutputStream output, final String value) throws IOException {
for (int i = 0; i < value.length(); i++) {
output.write(value.charAt(i));
}
}
Comment utiliser
Il est très simple à utiliser. Il suffit d'appeler comme ceci:
File f1 = new File("/sdcard/44100Sampling-16bit-mono-mic.pcm"); // The location of your PCM file
File f2 = new File("/sdcard/44100Sampling-16bit-mono-mic.wav"); // The location where you want your WAV file
try {
rawToWave(f1, f2);
} catch (IOException e) {
e.printStackTrace();
}
Comment tout cela fonctionne
Comme vous pouvez le voir, l'en-tête de WAV est la seule différence entre les formats de fichiers WAV et PCM. L'hypothèse est que vous enregistrez 16 bits PCM MONO audio (qui selon votre code, vous êtes). La fonction rawToWave ajoute simplement des en-têtes au fichier WAV, afin que les lecteurs de musique sachent à quoi s'attendre lorsque votre fichier est ouvert, puis après les en-têtes, il écrit simplement les données PCM à partir du dernier bit.
Cool Tip
Si vous voulez changer le ton de votre voix, ou faire une application changeur de voix, tout ce que vous avez à faire est d'augmenter/diminuer la valeur du writeInt(output, 44100); // sample rate
dans votre code. Diminuer cela indiquera au joueur de le jouer à un taux différent changeant ainsi la hauteur de sortie. Juste un petit quelque chose de plus intéressant à savoir. :)
Pourriez-vous lier la mise en œuvre de votre bibliothèque? –
@LeifGruenwoldt Ceci est une réponse de 5 ans, je suis désolé mais je ne l'ai pas autour. –