web-dev-qa-db-fra.com

Utiliser AudioTrack sous Android pour lire un fichier WAV

Je travaille avec Android, essayant de faire en sorte que mon application AudioTrack joue un fichier Windows .wav (Tada.wav). Franchement, ça ne devrait pas être si difficile, mais j'entends beaucoup de choses étranges. Le fichier est enregistré sur la mini carte SD de mon téléphone et la lecture du contenu ne semble pas poser de problème, mais lorsque je lis le fichier (avec les paramètres, je ne suis que TRÈS SUR), je reçois quelques secondes de bruit blanc. avant que le son semble se résoudre en quelque chose qui peut être juste.

J'ai enregistré et reproduit avec succès ma propre voix au téléphone. J'ai créé un fichier .pcm conformément aux instructions données dans cet exemple:

http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-Android.html

(sans le masquage en arrière) ...

Quelqu'un a-t-il des suggestions ou une connaissance d'un exemple sur le Web pour lire un fichier .wav sur un Android?

Merci, R.

23
Rich

Je suis tombé sur la réponse (franchement, en essayant & ^ @! Je ne pensais pas que cela fonctionnerait), au cas où quelqu'un serait intéressé ... Dans mon code d'origine (dérivé de l'exemple du lien dans le message d'origine), les données sont lues à partir du fichier comme suit:

    InputStream             is  = new FileInputStream       (file);
    BufferedInputStream     bis = new BufferedInputStream   (is, 8000);
    DataInputStream         dis = new DataInputStream       (bis);      //  Create a DataInputStream to read the audio data from the saved file

    int i = 0;                                                          //  Read the file into the "music" array
    while (dis.available() > 0)
    {
        music[i] = dis.readShort();                                     //  This assignment does not reverse the order
        i++;
    }

    dis.close();                                                        //  Close the input stream

Dans cette version, music [] est un tableau de SHORTS. Donc, la méthode readShort () semble avoir un sens ici, puisque les données sont en PCM 16 bits ... Cependant, sur Android, cela semble être le problème. J'ai changé ce code comme suit:

     music=new byte[(int) file.length()];//size & length of the file
    InputStream             is  = new FileInputStream       (file);
    BufferedInputStream     bis = new BufferedInputStream   (is, 8000);
    DataInputStream         dis = new DataInputStream       (bis);      //  Create a DataInputStream to read the audio data from the saved file

    int i = 0;                                                          //  Read the file into the "music" array
    while (dis.available() > 0)
    {
        music[i] = dis.readByte();                                      //  This assignment does not reverse the order
        i++;
    }

    dis.close();                                                        //  Close the input stream

Dans cette version, music [] est un tableau de BYTES. Je dis toujours à AudioTrack que ce sont des données PCM 16 bits, et mon Android ne semble pas avoir de problème pour écrire un tableau d'octets dans un AudioTrack ainsi configuré ... Quoi qu'il en soit, ça sonne bien, alors les autres veulent jouer des sons Windows sur leur Android, pour une raison quelconque, c'est la solution. Ah, Endianness ......

R.

26
Rich

J'ai trouvé beaucoup de réponses longues à cette question. Ma solution finale, qui compte tenu de tout le copier-coller, n’est guère mienne, se résume à:

public boolean play() {

    int i = 0;
    byte[] music = null;
    InputStream is = mContext.getResources().openRawResource(R.raw.noise);

    at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
        AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
        minBufferSize, AudioTrack.MODE_STREAM);

    try{
        music = new byte[512];
        at.play();

        while((i = is.read(music)) != -1)
            at.write(music, 0, i);

    } catch (IOException e) {
        e.printStackTrace();
    }

    at.stop();
    at.release();
    return STOPPED;
}

STOPPED est juste un "vrai" renvoyé comme un signal pour réinitialiser le bouton pause/lecture. Et dans l'initialiseur de classe:

public Mp3Track(Context context) {
    mContext = context;
    minBufferSize = AudioTrack.getMinBufferSize(44100,
        AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
}

Le contexte est juste "ceci" dans l'activité d'appel. Vous pouvez utiliser un FileInputStream sur la carte SD, etc. Mes fichiers sont en res/raw

8
R Earle Harris

Sautez-vous les 44 premiers octets du fichier avant de vider le reste des données du fichier dans la mémoire tampon? Les 44 premiers octets constituent l'en-tête WAVE et ils ressemblent à du bruit aléatoire si vous essayez de les lire.

Aussi, êtes-vous sûr de créer AudioTrack avec les mêmes propriétés que le WAVE que vous essayez de jouer (taux d'échantillonnage, débit binaire, nombre de canaux, etc.)? Windows vous fournit effectivement ces informations dans la page Propriétés du fichier: alt text

5
Aaron C

Comme dit par Aaron C , vous devez sauter les 44 octets initiaux ou (comme je le préfère) lire les 44 premiers octets qui sont l’en-tête WAVE. De cette façon, vous savez combien de canaux, de bits par échantillon, de longueur, etc. le WAVE contient.

Ici vous pouvez trouver une bonne implémentation d’un analyseur/rédacteur d’en-tête WAVE.

2
sixro

S'il vous plaît ne perpétuez pas de code d'analyse terrible. L’analyse WAV est simple à implémenter http://soundfile.sapp.org/doc/WaveFormat/ Et vous vous en remercierez en analysant des éléments tels que le taux d’échantillonnage , la profondeur de bits et le nombre de canaux.

De plus, x86 et ARM (au moins par défaut) sont tous deux de petite taille, de sorte que les fichiers WAV natifs doivent être corrects, sans aucune réorganisation.

1
yano

Exemple de fichier wav:
http://www.mauvecloud.net/sounds/pcm1644m.wav

Exemple de code:

public class AudioTrackPlayer {
Context mContext;
int minBufferSize;
AudioTrack at;
boolean STOPPED;

public AudioTrackPlayer(Context context) {
    Log.d("------","init");
    mContext = context;
    minBufferSize = AudioTrack.getMinBufferSize(44100,
            AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
}

public boolean play() {
    Log.d("------","play");
    int i = 0;
    byte[] music = null;
    InputStream is = mContext.getResources().openRawResource(R.raw.pcm1644m);

    at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
            AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
            minBufferSize, AudioTrack.MODE_STREAM);
    try {
        music = new byte[512];
        at.play();

        while ((i = is.read(music)) != -1)
            at.write(music, 0, i);

    } catch (IOException e) {
        e.printStackTrace();
    }
    at.stop();
    at.release();
    return STOPPED;
}

}

0
Yang