def to_pcm(self): if (self.filename.endswith(".wv")): if ('-r' in WavPackAudio.__wvunpack_help__()): sub = subprocess.Popen([ BIN['wvunpack'], '-q', '-y', self.filename, '-r', '-o', '-' ], stdout=subprocess.PIPE, stderr=file(os.devnull, 'ab')) return PCMReader(sub.stdout, sample_rate=self.sample_rate(), channels=self.channels(), channel_mask=int(self.channel_mask()), bits_per_sample=self.bits_per_sample(), process=sub) else: sub = subprocess.Popen( [BIN['wvunpack'], '-q', '-y', self.filename, '-o', '-'], stdout=subprocess.PIPE, stderr=file(os.devnull, 'ab')) return WaveReader(sub.stdout, sample_rate=self.sample_rate(), channels=self.channels(), channel_mask=int(self.channel_mask()), bits_per_sample=self.bits_per_sample(), process=sub) else: #create a temporary symlink to the current file #rather than rewrite the whole thing (tempdir, symlink) = SymlinkPCMReader.new(self.filename, ".wv") return SymlinkPCMReader( WavPackAudio(symlink).to_pcm(), tempdir, symlink)
def to_pcm(self): #if mpg123 is available, use that for decoding if (BIN.can_execute(BIN["mpg123"])): sub = subprocess.Popen([BIN["mpg123"],"-qs",self.filename], stdout=subprocess.PIPE, stderr=file(os.devnull,"a")) return PCMReader(sub.stdout, sample_rate=self.sample_rate(), channels=self.channels(), bits_per_sample=16, channel_mask=int(ChannelMask.from_channels(self.channels())), process=sub, big_endian=BIG_ENDIAN) else: #if not, use LAME for decoding if (self.filename.endswith("." + self.SUFFIX)): if (BIG_ENDIAN): endian = ['-x'] else: endian = [] sub = subprocess.Popen([BIN['lame']] + endian + \ ["--decode","-t","--quiet", self.filename,"-"], stdout=subprocess.PIPE) return PCMReader(sub.stdout, sample_rate=self.sample_rate(), channels=self.channels(), bits_per_sample=16, channel_mask=int(ChannelMask.from_channels(self.channels())), process=sub) else: import tempfile from audiotools import TempWaveReader #copy our file to one that ends with .mp3 tempmp3 = tempfile.NamedTemporaryFile(suffix='.' + self.SUFFIX) f = open(self.filename,'rb') transfer_data(f.read,tempmp3.write) f.close() tempmp3.flush() #decode the mp3 file to a WAVE file wave = tempfile.NamedTemporaryFile(suffix='.wav') returnval = subprocess.call([BIN['lame'],"--decode","--quiet", tempmp3.name,wave.name]) tempmp3.close() if (returnval == 0): #return WAVE file as a stream wave.seek(0,0) return TempWaveReader(wave) else: return PCMReaderError(None, sample_rate=self.sample_rate(), channels=self.channels(), bits_per_sample=16)
def to_wave(self, wave_filename): devnull = file(os.devnull, 'ab') #WavPack stupidly refuses to run if the filename doesn't end with .wv if (self.filename.endswith(".wv")): sub = subprocess.Popen([ BIN['wvunpack'], '-q', '-y', self.filename, '-o', wave_filename ], stdout=devnull, stderr=devnull) if (sub.wait() != 0): raise EncodingError() else: #create a temporary symlink to the current file #rather than rewrite the whole thing import tempfile tempdir = tempfile.mkdtemp() symlink = os.path.join(tempdir, os.path.basename(self.filename) + ".wv") try: os.symlink(os.path.abspath(self.filename), symlink) WavPackAudio(symlink).to_wave(wave_filename) finally: os.unlink(symlink) os.rmdir(tempdir)
def from_pcm(cls, filename, pcmreader, compression=None): """Returns a PCMReader object containing the track's PCM data.""" if ((compression is None) or (compression not in cls.COMPRESSION_MODES)): compression = __default_quality__(cls.NAME) devnull = file(os.devnull, 'ab') sub = subprocess.Popen([ BIN['oggenc'], '-Q', '-r', '-B', str(pcmreader.bits_per_sample), '-C', str(pcmreader.channels), '-R', str(pcmreader.sample_rate), '--raw-endianness', str(0), '-q', compression, '-o', filename, '-' ], stdin=subprocess.PIPE, stdout=devnull, stderr=devnull, preexec_fn=ignore_sigint) if ((pcmreader.channels <= 2) or (int(pcmreader.channel_mask) == 0)): try: transfer_framelist_data(pcmreader, sub.stdin.write) except (IOError, ValueError), err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise EncodingError(str(err)) except Exception, err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise err
def from_pcm(cls, filename, pcmreader, compression="2"): import decimal,bisect if (compression not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION if ((pcmreader.channels > 2) or (pcmreader.sample_rate not in (32000,48000,44100))): pcmreader = PCMConverter( pcmreader, sample_rate=[32000,32000,44100,48000][bisect.bisect( [32000,44100,48000],pcmreader.sample_rate)], channels=min(pcmreader.channels,2), channel_mask=ChannelMask.from_channels(min(pcmreader.channels,2)), bits_per_sample=16) if (pcmreader.channels > 1): mode = "j" else: mode = "m" #FIXME - not sure if all LAME versions support "--little-endian" # #LAME 3.98 (and up, presumably) handle the byteswap correctly # #LAME 3.97 always uses -x # if (BIG_ENDIAN or (cls.__lame_version__() < (3,98))): # endian = ['-x'] # else: # endian = [] devnull = file(os.devnull,'ab') sub = subprocess.Popen([BIN['lame'],"--quiet", "-r", "-s",str(decimal.Decimal(pcmreader.sample_rate) / 1000), "--bitwidth",str(pcmreader.bits_per_sample), "--signed","--little-endian", "-m",mode, "-V" + str(compression), "-", filename], stdin=subprocess.PIPE, stdout=devnull, stderr=devnull, preexec_fn=ignore_sigint) transfer_framelist_data(pcmreader,sub.stdin.write) try: pcmreader.close() except DecodingError: raise EncodingError() sub.stdin.close() devnull.close() if (sub.wait() == 0): return MP3Audio(filename) else: raise EncodingError(BIN['lame'])
def to_pcm(self): sub = subprocess.Popen([ BIN['oggdec'], '-Q', '-b', str(16), '-e', str(0), '-s', str(1), '-R', '-o', '-', self.filename ], stdout=subprocess.PIPE, stderr=file(os.devnull, "a")) pcmreader = PCMReader(sub.stdout, sample_rate=self.sample_rate(), channels=self.channels(), channel_mask=int(self.channel_mask()), bits_per_sample=self.bits_per_sample(), process=sub) if (self.channels() <= 2): return pcmreader elif (self.channels() <= 8): #these mappings transform Vorbis order into ChannelMask order standard_channel_mask = self.channel_mask() vorbis_channel_mask = VorbisChannelMask(self.channel_mask()) return ReorderedPCMReader(pcmreader, [ vorbis_channel_mask.channels().index(channel) for channel in standard_channel_mask.channels() ]) else: return pcmreader
def __help_output__(cls): import cStringIO help_data = cStringIO.StringIO() sub = subprocess.Popen([BIN['lame'],'--help'], stdout=subprocess.PIPE) transfer_data(sub.stdout.read,help_data.write) sub.wait() return help_data.getvalue()
def __wvunpack_help__(cls): devnull = open(os.devnull, "wb") sub = subprocess.Popen([BIN["wvunpack"], "--help"], stdout=subprocess.PIPE, stderr=devnull) help_data = sub.stdout.read() sub.stdout.close() devnull.close() sub.wait() return help_data
def from_pcm(cls, filename, pcmreader, compression=None): """Encodes a new file from PCM data. Takes a filename string, PCMReader object and optional compression level string. Encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new SpeexAudio object.""" import bisect if ((compression is None) or (compression not in cls.COMPRESSION_MODES)): compression = __default_quality__(cls.NAME) if ((pcmreader.bits_per_sample not in (8, 16)) or (pcmreader.channels > 2) or (pcmreader.sample_rate not in (8000, 16000, 32000, 44100))): pcmreader = PCMConverter( pcmreader, sample_rate=[8000, 8000, 16000, 32000, 44100][bisect.bisect([8000, 16000, 32000, 44100], pcmreader.sample_rate)], channels=min(pcmreader.channels, 2), channel_mask=ChannelMask.from_channels( min(pcmreader.channels, 2)), bits_per_sample=min(pcmreader.bits_per_sample, 16)) BITS_PER_SAMPLE = { 8: ['--8bit'], 16: ['--16bit'] }[pcmreader.bits_per_sample] CHANNELS = {1: [], 2: ['--stereo']}[pcmreader.channels] devnull = file(os.devnull, "ab") sub = subprocess.Popen([BIN['speexenc'], '--quality', str(compression), '--rate', str(pcmreader.sample_rate), '--le'] + \ BITS_PER_SAMPLE + \ CHANNELS + \ ['-', filename], stdin=subprocess.PIPE, stderr=devnull, preexec_fn=ignore_sigint) try: transfer_framelist_data(pcmreader, sub.stdin.write) except (IOError, ValueError), err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise EncodingError(str(err))
def from_pcm(cls, filename, pcmreader, compression=None): if (compression not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION devnull = file(os.devnull, 'ab') sub = subprocess.Popen([ BIN['oggenc'], '-Q', '-r', '-B', str(pcmreader.bits_per_sample), '-C', str(pcmreader.channels), '-R', str(pcmreader.sample_rate), '--raw-endianness', str(0), '-q', compression, '-o', filename, '-' ], stdin=subprocess.PIPE, stdout=devnull, stderr=devnull, preexec_fn=ignore_sigint) if ((pcmreader.channels <= 2) or (int(pcmreader.channel_mask) == 0)): transfer_framelist_data(pcmreader, sub.stdin.write) elif (pcmreader.channels <= 8): if (int(pcmreader.channel_mask) in ( 0x7, #FR, FC, FL 0x33, #FR, FL, BR, BL 0x37, #FR, FC, FL, BL, BR 0x3f, #FR, FC, FL, BL, BR, LFE 0x70f, #FL, FC, FR, SL, SR, BC, LFE 0x63f) #FL, FC, FR, SL, SR, BL, BR, LFE ): standard_channel_mask = ChannelMask(pcmreader.channel_mask) vorbis_channel_mask = VorbisChannelMask(standard_channel_mask) else: raise UnsupportedChannelMask() transfer_framelist_data( ReorderedPCMReader(pcmreader, [ standard_channel_mask.channels().index(channel) for channel in vorbis_channel_mask.channels() ]), sub.stdin.write) else: raise UnsupportedChannelMask() try: pcmreader.close() except DecodingError: raise EncodingError() sub.stdin.close() devnull.close() if (sub.wait() == 0): return VorbisAudio(filename) else: raise EncodingError(BIN['oggenc'])
def to_pcm(self): devnull = file(os.devnull,'ab') sub = subprocess.Popen([BIN['speexdec'],self.filename,'-'], stdout=subprocess.PIPE, stderr=devnull) return PCMReader( sub.stdout, sample_rate=self.sample_rate(), channels=self.channels(), channel_mask=int(ChannelMask.from_channels(self.channels())), bits_per_sample=self.bits_per_sample(), process=sub)
def from_wave(cls, filename, wave_filename, compression=None): if (str(compression) not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION devnull = file(os.devnull, "wb") sub = subprocess.Popen( [BIN['mac'], wave_filename, filename, "-c%s" % (compression)], stdout=devnull, stderr=devnull) sub.wait() devnull.close() return ApeAudio(filename)
def to_wave(self, wave_filename): if (self.filename.endswith(".ape")): devnull = file(os.devnull, "wb") sub = subprocess.Popen( [BIN['mac'], self.filename, wave_filename, '-d'], stdout=devnull, stderr=devnull) sub.wait() devnull.close() else: devnull = file(os.devnull, 'ab') import tempfile ape = tempfile.NamedTemporaryFile(suffix='.ape') f = file(self.filename, 'rb') transfer_data(f.read, ape.write) f.close() ape.flush() sub = subprocess.Popen([BIN['mac'], ape.name, wave_filename, '-d'], stdout=devnull, stderr=devnull) sub.wait() ape.close() devnull.close()
def from_pcm(cls, filename, pcmreader, compression=None): """Encodes a new file from PCM data. Takes a filename string, PCMReader object and optional compression level string. Encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new MP2Audio object.""" import decimal import bisect if ((compression is None) or (compression not in cls.COMPRESSION_MODES)): compression = __default_quality__(cls.NAME) if ((pcmreader.channels > 2) or (pcmreader.sample_rate not in (32000, 48000, 44100)) or (pcmreader.bits_per_sample != 16)): pcmreader = PCMConverter( pcmreader, sample_rate=[32000, 32000, 44100, 48000][bisect.bisect( [32000, 44100, 48000], pcmreader.sample_rate)], channels=min(pcmreader.channels, 2), channel_mask=pcmreader.channel_mask, bits_per_sample=16) devnull = file(os.devnull, 'ab') sub = subprocess.Popen([BIN['twolame'], "--quiet", "-r", "-s", str(pcmreader.sample_rate), "--samplesize", str(pcmreader.bits_per_sample), "-N", str(pcmreader.channels), "-m", "a", "-b", compression, "-", filename], stdin=subprocess.PIPE, stdout=devnull, stderr=devnull, preexec_fn=ignore_sigint) try: transfer_framelist_data(pcmreader, sub.stdin.write) except (ValueError, IOError), err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise EncodingError(str(err))
def add_replay_gain(cls, filenames): track_names = [track.filename for track in open_files(filenames) if isinstance(track,cls)] if ((len(track_names) > 0) and (BIN.can_execute(BIN['mp3gain']))): devnull = file(os.devnull,'ab') sub = subprocess.Popen([BIN['mp3gain'],'-f','-k','-q','-r'] + \ track_names, stdout=devnull, stderr=devnull) sub.wait() devnull.close()
def from_pcm(cls, filename, pcmreader, compression=None): import bisect if (compression not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION if ((pcmreader.bits_per_sample not in (8,16)) or (pcmreader.channels > 2) or (pcmreader.sample_rate not in (8000,16000,32000,44100))): pcmreader = PCMConverter( pcmreader, sample_rate=[8000,8000,16000,32000,44100][bisect.bisect( [8000,16000,32000,44100],pcmreader.sample_rate)], channels=min(pcmreader.channels,2), channel_mask=ChannelMask.from_channels(min(pcmreader.channels,2)), bits_per_sample=min(pcmreader.bits_per_sample,16)) BITS_PER_SAMPLE = {8:['--8bit'], 16:['--16bit']}[pcmreader.bits_per_sample] CHANNELS = {1:[],2:['--stereo']}[pcmreader.channels] devnull = file(os.devnull,"ab") sub = subprocess.Popen([BIN['speexenc'], '--quality',str(compression), '--rate',str(pcmreader.sample_rate), '--le'] + \ BITS_PER_SAMPLE + \ CHANNELS + \ ['-',filename], stdin=subprocess.PIPE, stderr=devnull, preexec_fn=ignore_sigint) transfer_framelist_data(pcmreader,sub.stdin.write) try: pcmreader.close() except DecodingError: raise EncodingError() sub.stdin.close() result = sub.wait() devnull.close() if (result == 0): return SpeexAudio(filename) else: raise EncodingError(BIN['speexenc'])
def from_pcm(cls, filename, pcmreader, compression="192"): import decimal,bisect if (compression not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION if ((pcmreader.channels > 2) or (pcmreader.sample_rate not in (32000,48000,44100)) or (pcmreader.bits_per_sample != 16)): pcmreader = PCMConverter( pcmreader, sample_rate=[32000,32000,44100,48000][bisect.bisect( [32000,44100,48000],pcmreader.sample_rate)], channels=min(pcmreader.channels,2), channel_mask=pcmreader.channel_mask, bits_per_sample=16) devnull = file(os.devnull,'ab') sub = subprocess.Popen([BIN['twolame'],"--quiet", "-r", "-s",str(pcmreader.sample_rate), "--samplesize",str(pcmreader.bits_per_sample), "-N",str(pcmreader.channels), "-m","a", "-b",compression, "-", filename], stdin=subprocess.PIPE, stdout=devnull, stderr=devnull, preexec_fn=ignore_sigint) transfer_framelist_data(pcmreader,sub.stdin.write) try: pcmreader.close() except DecodingError: raise EncodingError() sub.stdin.close() devnull.close() if (sub.wait() == 0): return MP2Audio(filename) else: raise EncodingError(BIN['twolame'])
def __to_wave__(self, wave_filename): devnull = file(os.devnull, "wb") try: sub = subprocess.Popen([BIN['mpcdec'], self.filename, wave_filename], stdout=devnull, stderr=devnull) #FIXME - small files (~5 seconds) result in an error by mpcdec, #even if they decode correctly. #Not much we can do except try to workaround its bugs. if (sub.wait() not in [0, 250]): raise DecodingError() finally: devnull.close()
def __from_wave__(cls, filename, wave_filename, compression=None): if (str(compression) not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION #mppenc requires files to end with .mpc for some reason if (not filename.endswith(".mpc")): import tempfile actual_filename = filename tempfile = tempfile.NamedTemporaryFile(suffix=".mpc") filename = tempfile.name else: actual_filename = tempfile = None ###Musepack SV7### #sub = subprocess.Popen([BIN['mppenc'], # "--silent", # "--overwrite", # "--%s" % (compression), # wave_filename, # filename], # preexec_fn=ignore_sigint) ###Musepack SV8### sub = subprocess.Popen([BIN['mpcenc'], "--silent", "--overwrite", "--%s" % (compression), wave_filename, filename]) if (sub.wait() == 0): if (tempfile is not None): filename = actual_filename f = file(filename, 'wb') tempfile.seek(0, 0) transfer_data(tempfile.read, f.write) f.close() tempfile.close() return MusepackAudio(filename) else: if (tempfile is not None): tempfile.close() raise EncodingError(u"error encoding file with mpcenc")
def from_wave(cls, filename, wave_filename, compression=None): if (str(compression) not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION compression_param = { "fast": ["-f"], "standard": [], "high": ["-h"], "veryhigh": ["-hh"] } #wavpack will add a .wv suffix if there isn't one #this isn't desired behavior if (filename.endswith(".wv")): devnull = file(os.devnull, 'ab') sub = subprocess.Popen([BIN['wavpack'], wave_filename] + \ compression_param[compression] + \ ['-q','-y','-o', filename], stdout=devnull, stderr=devnull, preexec_fn=ignore_sigint) devnull.close() if (sub.wait() == 0): return WavPackAudio(filename) else: raise EncodingError(BIN['wavpack']) else: import tempfile tempdir = tempfile.mkdtemp() symlink = os.path.join(tempdir, os.path.basename(filename) + ".wv") try: os.symlink(os.path.abspath(filename), symlink) cls.from_wave(symlink, wave_filename, compression) return WavPackAudio(filename) finally: os.unlink(symlink) os.rmdir(tempdir)
def add_replay_gain(cls, filenames): """Adds ReplayGain values to a list of filename strings. All the filenames must be of this AudioFile type. Raises ValueError if some problem occurs during ReplayGain application. """ track_names = [track.filename for track in open_files(filenames) if isinstance(track, cls)] if ((len(track_names) > 0) and (BIN.can_execute(BIN['mp3gain']))): devnull = file(os.devnull, 'ab') sub = subprocess.Popen([BIN['mp3gain'], '-f', '-k', '-q', '-r'] + \ track_names, stdout=devnull, stderr=devnull) sub.wait() devnull.close()
def from_pcm(cls, filename, pcmreader, compression=None): compression_param = { "fast": ["-f"], "standard": [], "high": ["-h"], "veryhigh": ["-hh"] } if (str(compression) not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION if ('--raw-pcm' in cls.__wavpack_help__()): if (filename.endswith(".wv")): devnull = file(os.devnull, 'ab') if (pcmreader.channels > 18): raise UnsupportedChannelMask() elif (pcmreader.channels > 2): order_map = { "front_left": "FL", "front_right": "FR", "front_center": "FC", "low_frequency": "LFE", "back_left": "BL", "back_right": "BR", "front_left_of_center": "FLC", "front_right_of_center": "FRC", "back_center": "BC", "side_left": "SL", "side_right": "SR", "top_center": "TC", "top_front_left": "TFL", "top_front_center": "TFC", "top_front_right": "TFR", "top_back_left": "TBL", "top_back_center": "TBC", "top_back_right": "TBR" } channel_order = [ "--channel-order=%s" % (",".join([ order_map[channel] for channel in ChannelMask( pcmreader.channel_mask).channels() ])) ] else: channel_order = [] sub = subprocess.Popen([BIN['wavpack']] + \ compression_param[compression] + \ ['-q','-y', "--raw-pcm=%(sr)s,%(bps)s,%(ch)s"%\ {"sr":pcmreader.sample_rate, "bps":pcmreader.bits_per_sample, "ch":pcmreader.channels}] + \ channel_order + \ ['-','-o',filename], stdout=devnull, stderr=devnull, stdin=subprocess.PIPE, preexec_fn=ignore_sigint) transfer_framelist_data(pcmreader, sub.stdin.write) devnull.close() sub.stdin.close() if (sub.wait() == 0): return WavPackAudio(filename) else: raise EncodingError(BIN['wavpack']) else: import tempfile tempdir = tempfile.mkdtemp() symlink = os.path.join(tempdir, os.path.basename(filename) + ".wv") try: os.symlink(os.path.abspath(filename), symlink) cls.from_pcm(symlink, pcmreader, compression) return WavPackAudio(filename) finally: os.unlink(symlink) os.rmdir(tempdir) else: import tempfile f = tempfile.NamedTemporaryFile(suffix=".wav") w = WaveAudio.from_pcm(f.name, pcmreader) try: return cls.from_wave(filename, w.filename, compression) finally: del (w) f.close()
def from_pcm(cls, filename, pcmreader, compression=None): """Encodes a new file from PCM data. Takes a filename string, PCMReader object and optional compression level string. Encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new MP3Audio object.""" import decimal import bisect if ((compression is None) or (compression not in cls.COMPRESSION_MODES)): compression = __default_quality__(cls.NAME) if ((pcmreader.channels > 2) or (pcmreader.sample_rate not in (32000, 48000, 44100))): pcmreader = PCMConverter( pcmreader, sample_rate=[32000, 32000, 44100, 48000][bisect.bisect( [32000, 44100, 48000], pcmreader.sample_rate)], channels=min(pcmreader.channels, 2), channel_mask=ChannelMask.from_channels( min(pcmreader.channels, 2)), bits_per_sample=16) if (pcmreader.channels > 1): mode = "j" else: mode = "m" #FIXME - not sure if all LAME versions support "--little-endian" # #LAME 3.98 (and up, presumably) handle the byteswap correctly # #LAME 3.97 always uses -x # if (BIG_ENDIAN or (cls.__lame_version__() < (3,98))): # endian = ['-x'] # else: # endian = [] devnull = file(os.devnull, 'ab') sub = subprocess.Popen([ BIN['lame'], "--quiet", "-r", "-s", str(decimal.Decimal(pcmreader.sample_rate) / 1000), "--bitwidth", str(pcmreader.bits_per_sample), "--signed", "--little-endian", "-m", mode, "-V" + str(compression), "-", filename], stdin=subprocess.PIPE, stdout=devnull, stderr=devnull, preexec_fn=ignore_sigint) try: transfer_framelist_data(pcmreader, sub.stdin.write) except (IOError, ValueError), err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise EncodingError(str(err))