Spaces:
Runtime error
Runtime error
File size: 3,566 Bytes
d82cf6a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
"""Decoder for RIFF Wave files, using the standard library wave module.
"""
import wave
from pyglet.util import DecodeException
from .base import StreamingSource, AudioData, AudioFormat, StaticSource
from . import MediaEncoder, MediaDecoder
class WAVEDecodeException(DecodeException):
pass
class WaveSource(StreamingSource):
def __init__(self, filename, file=None):
if file is None:
file = open(filename, 'rb')
self._file = file
try:
self._wave = wave.open(file)
except wave.Error as e:
raise WAVEDecodeException(e)
nchannels, sampwidth, framerate, nframes, comptype, compname = self._wave.getparams()
self.audio_format = AudioFormat(channels=nchannels, sample_size=sampwidth * 8, sample_rate=framerate)
self._bytes_per_frame = nchannels * sampwidth
self._duration = nframes / framerate
self._duration_per_frame = self._duration / nframes
self._num_frames = nframes
self._wave.rewind()
def __del__(self):
if hasattr(self, '_file'):
self._file.close()
def get_audio_data(self, num_bytes, compensation_time=0.0):
num_frames = max(1, num_bytes // self._bytes_per_frame)
data = self._wave.readframes(num_frames)
if not data:
return None
timestamp = self._wave.tell() / self.audio_format.sample_rate
duration = num_frames / self.audio_format.sample_rate
return AudioData(data, len(data), timestamp, duration, [])
def seek(self, timestamp):
timestamp = max(0.0, min(timestamp, self._duration))
position = int(timestamp / self._duration_per_frame)
self._wave.setpos(position)
#########################################
# Decoder class:
#########################################
class WaveDecoder(MediaDecoder):
def get_file_extensions(self):
return '.wav', '.wave', '.riff'
def decode(self, filename, file, streaming=True):
if streaming:
return WaveSource(filename, file)
else:
return StaticSource(WaveSource(filename, file))
class WaveEncoder(MediaEncoder):
def get_file_extensions(self):
return '.wav', '.wave', '.riff'
def encode(self, source, filename, file):
"""Save the Source to disk as a standard RIFF Wave.
A standard RIFF wave header will be added to the raw PCM
audio data when it is saved to disk.
:Parameters:
`filename` : str
The file name to save as.
`file` : file-like object
A file-like object, opened with mode 'wb'.
"""
opened_file = None
if file is None:
file = open(filename, 'wb')
opened_file = True
source.seek(0)
wave_writer = wave.open(file, mode='wb')
wave_writer.setnchannels(source.audio_format.channels)
wave_writer.setsampwidth(source.audio_format.bytes_per_sample)
wave_writer.setframerate(source.audio_format.sample_rate)
# Save the data in 1-second chunks:
chunksize = source.audio_format.bytes_per_second
audiodata = source.get_audio_data(chunksize)
while audiodata:
wave_writer.writeframes(audiodata.data)
audiodata = source.get_audio_data(chunksize)
else:
wave_writer.close()
if opened_file:
file.close()
def get_decoders():
return [WaveDecoder()]
def get_encoders():
return [WaveEncoder()]
|