Modifier le volume d'un fichier wav en python

J'ai un 2 secondes 16 bits de canal unique de 8 khz wav fichier et j'ai besoin de changer son volume.

Il devrait être assez simple, parce que changer le volume est le même que la modification de l'amplitude du signal, et j'ai juste besoin de l'atténuer, c'est-à multiplier par un nombre entre 0 et 1. Mais ça ne fonctionne pas: le nouveau son est plus faible, mais TRÈS bruyant. Ce que je fais mal?

Voici mon code:

import wave, numpy, struct

# Open
w = wave.open("input.wav","rb")
p = w.getparams()
f = p[3] # number of frames
s = w.readframes(f)
w.close()

# Edit
s = numpy.fromstring(s, numpy.int16) * 5 / 10  # half amplitude
s = struct.pack('h'*len(s), *s)

# Save
w = wave.open("output.wav","wb")
w.setparams(p)
w.writeframes(s)
w.close()

Merci les gars!

  • Pourquoi êtes-vous à l'aide de * 5 / 10 au lieu de / 2?
  • Si je devais deviner, je dirais que le * 5 partie est de clipping et de débordement.
  • Êtes-vous de lire le fichier dans le bon boutisme? les fichiers WAV sont little-endian. à l'Aide de l'autre endian permettra de réduire de moitié l'échantillon et ajouter BEAUCOUP de bruit.
  • Oh mon...!! Désolé pour l'affichage que... La réponse a été trop facile. En procédant ainsi: s = numpy.fromstring(s, numpy.int16) * 5 / 10 # la moitié de l'amplitude Du signal est saturé, parce que j'ai multiplié les entiers avant de les diviser. Une solution: s = numpy.fromstring(s, numpy.int16) / 10 * 5 # la moitié de l'amplitude attention, cela ne fonctionne PAS comme les résultats de la division zéro: s = numpy.fromstring(s, numpy.int16) * (5 / 10) # la moitié de l'amplitude, je le garde ici au cas où il permet à quelqu'un d'autre.
  • Jan, parce qu'ils sont censés être vars: 5 volume souhaité, puis 10 est le volume original.
  • Nick, OUI!! Vous êtes de droite. Merci!!!!
  • Vous devriez poster votre commentaire comme une réponse et de l'accepter quand c'est possible (+24h IIRC)
  • Merci Jan, mais stackoverflow me permet d'attendre encore 7 heures avant que je puisse poster une réponse... 🙂
  • Depuis que vous avez trouvé le problème, il serait juste si vous avez posté une réponse et l'OP accepté. Une solution complète serait probablement inclure multipliant avec float(desired_volume) / float(orig_volume).
  • Dommage que je ne suis pas à l'aise en python. Je ne savais même pas si python n'utilisez pas les types float pour tout.
  • Une autre chose: le * opérateur dans struct.pack('h', *s) ligne convertit l'ensemble du tableau numpy dans un tuple de type int objets. C'est potentiellement très efficace, vous devez utiliser les s.tostring au lieu de cela, ce qui permettra de créer efficacement une chaîne directement à partir du contenu du tableau.
  • Si il est mis à l'échelle par un flotteur, en utilisant seulement tostring va donner un mauvais résultat. Mais au lieu de cela, vous pourriez faire s = (s * (desired/original)).astype(numpy.int16).tostring().

InformationsquelleAutor Ricard Bou | 2012-11-11