J'essaie d'écrire un programme pour afficher les données PCM. J'ai été très frustré en essayant de trouver une bibliothèque avec le bon niveau d'abstraction, mais j'ai trouvé la bibliothèque de l'onde Python et utilisez cela. Cependant, je ne sais pas comment interpréter les données. P>
La fonction wave.geparams retourne (2 canaux, 2 octets, 44100 Hz, 96333 images, aucune compression, aucune compression). Tout cela semble joyeux, mais j'ai ensuite essayé d'imprimer une seule image: '\ xc0 \ xff \ xd0 \ xff' qui est 4 octets. Je suppose qu'il est possible qu'un cadre soit 2 échantillons, mais les ambiguïtés ne s'arrêtent pas là. P>
96333 cadres * 2 échantillons / cadre * (1/44.1k sec / échantillon) = 4,3688 secondes p>
Cependant, iTunes signale le temps aussi près de 2 secondes et les calculs basés sur la taille et le débit de fichier sont dans le ballon de 2,7 secondes. Qu'est-ce qui se passe ici? P>
En outre, comment dois-je savoir si les octets sont signés ou non signés? P>
Merci beaucoup! P>
6 Réponses :
"Deux canaux" signifie stéréo, il n'est donc pas logique de somme em> chaque canal - de sorte que vous êtes éteint d'un facteur de deux (2,18 secondes, pas de 4,37). Quant à la signature, comme expliqué par exemple ici , et je cite: p>
Les échantillons de 8 bits sont stockés comme non signé
octets, allant de 0 à 255. 16 bits
Les échantillons sont stockés sous forme de 2's-complément
nombres entiers signés, allant de -32768
à 32767. P>
blockQuote>
Ceci fait partie des spécifications du format WAV (en fait de son riff de Superset) et ne dépend donc pas de quelle bibliothèque utilisée pour traiter un fichier WAV. P>
Merci! Je ne peux qu'espérer que c'était mon manque de sommeil qui m'a empêché de remarquer le numéro stéréo ;-)
Chaque échantillon est de 16 bits et il y a 2 canaux, donc le cadre prend 4 octets p>
La durée est simplement le nombre de cadres divisé par le nombre de cadres par seconde. À partir de vos données, c'est: 96333/44100 = 2,18 secondes code>. P>
Je sais qu'une réponse a déjà été acceptée, mais j'ai fait des choses avec audio il y a quelque temps et que vous devez décompresser la vague à faire quelque chose comme ça. Aussi, un paquet que j'ai utilisé s'appelait Pyaudio, même si je devais toujours utiliser le paquet de vagues avec elle. p> p>
Merci de votre aide! Je l'ai travaillé et je posterai la solution ici pour que tout le monde soit utilisé au cas où une autre pauvre âme a besoin:
import wave import struct def pcm_channels(wave_file): """Given a file-like object or file path representing a wave file, decompose it into its constituent PCM data streams. Input: A file like object or file path Output: A list of lists of integers representing the PCM coded data stream channels and the sample rate of the channels (mixed rate channels not supported) """ stream = wave.open(wave_file,"rb") num_channels = stream.getnchannels() sample_rate = stream.getframerate() sample_width = stream.getsampwidth() num_frames = stream.getnframes() raw_data = stream.readframes( num_frames ) # Returns byte data stream.close() total_samples = num_frames * num_channels if sample_width == 1: fmt = "%iB" % total_samples # read unsigned chars elif sample_width == 2: fmt = "%ih" % total_samples # read signed 2 byte shorts else: raise ValueError("Only supports 8 and 16 bit audio formats.") integer_data = struct.unpack(fmt, raw_data) del raw_data # Keep memory tidy (who knows how big it might be) channels = [ [] for time in range(num_channels) ] for index, value in enumerate(integer_data): bucket = index % num_channels channels[bucket].append(value) return channels, sample_rate
bâtiment sur Cette réponse , vous pouvez obtenir une bonne performance en utilisant numpy.fromstring ou numpy.fromfile . Voir aussi Cette réponse .
Voici ce que j'ai fait: P>
def interpret_wav(raw_bytes, n_frames, n_channels, sample_width, interleaved = True): if sample_width == 1: dtype = np.uint8 # unsigned char elif sample_width == 2: dtype = np.int16 # signed 2-byte short else: raise ValueError("Only supports 8 and 16 bit audio formats.") channels = np.fromstring(raw_bytes, dtype=dtype) if interleaved: # channels are interleaved, i.e. sample N of channel M follows sample N of channel M-1 in raw data channels.shape = (n_frames, n_channels) channels = channels.T else: # channels are not interleaved. All samples from channel M occur before all samples from channel M-1 channels.shape = (n_channels, n_frames) return channels