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 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 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 MusepackAudio object.""" import tempfile import bisect if (str(compression) not in cls.COMPRESSION_MODES): compression = cls.DEFAULT_COMPRESSION if ((pcmreader.channels > 2) or (pcmreader.sample_rate not in (44100, 48000, 37800, 32000)) or (pcmreader.bits_per_sample != 16)): pcmreader = PCMConverter( pcmreader, sample_rate=[32000, 32000, 37800, 44100, 48000][bisect.bisect( [32000, 37800, 44100, 48000], pcmreader.sample_rate)], channels=min(pcmreader.channels, 2), bits_per_sample=16) f = tempfile.NamedTemporaryFile(suffix=".wav") w = WaveAudio.from_pcm(f.name, pcmreader) try: return cls.__from_wave__(filename, f.name, compression) finally: del(w) f.close()
def from_pcm(cls, filename, pcmreader, compression=None, total_pcm_frames=None): """encodes a new file from PCM data takes a filename string, PCMReader object, optional compression level string and optional total_pcm_frames integer encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new MP2Audio object""" from audiotools import (PCMConverter, BufferedPCMReader, ChannelMask, __default_quality__, EncodingError) from audiotools.encoders import encode_mp2 import bisect if (((compression is None) or (compression not in cls.COMPRESSION_MODES))): compression = __default_quality__(cls.NAME) if pcmreader.sample_rate in (32000, 48000, 44100): sample_rate = pcmreader.sample_rate else: sample_rate = [32000, 32000, 44100, 48000][bisect.bisect([32000, 44100, 48000], pcmreader.sample_rate)] if total_pcm_frames is not None: from audiotools import CounterPCMReader pcmreader = CounterPCMReader(pcmreader) try: encode_mp2(filename, PCMConverter(pcmreader, sample_rate=sample_rate, channels=min(pcmreader.channels, 2), channel_mask=ChannelMask.from_channels( min(pcmreader.channels, 2)), bits_per_sample=16), int(compression)) if ((total_pcm_frames is not None) and (total_pcm_frames != pcmreader.frames_written)): from audiotools.text import ERR_TOTAL_PCM_FRAMES_MISMATCH cls.__unlink__(filename) raise EncodingError(ERR_TOTAL_PCM_FRAMES_MISMATCH) return MP2Audio(filename) except (ValueError, IOError) as err: cls.__unlink__(filename) raise EncodingError(str(err)) finally: pcmreader.close()
def from_pcm(cls, filename, pcmreader, compression=None, total_pcm_frames=None): """encodes a new file from PCM data takes a filename string, PCMReader object, optional compression level string and optional total_pcm_frames integer encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new AudioFile-compatible object may raise EncodingError if some problem occurs when encoding the input file. This includes an error in the input stream, a problem writing the output file, or even an EncodingError subclass such as "UnsupportedBitsPerSample" if the input stream is formatted in a way this class is unable to support """ from audiotools import (BufferedPCMReader, PCMConverter, __default_quality__, EncodingError) from audiotools.encoders import encode_opus if (((compression is None) or (compression not in cls.COMPRESSION_MODES))): compression = __default_quality__(cls.NAME) if ((pcmreader.channels > 2) and (pcmreader.channels <= 8)): channel_mask = int(pcmreader.channel_mask) if ((channel_mask != 0) and (channel_mask not 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 raise UnsupportedChannelMask(filename, channel_mask) try: encode_opus(filename, BufferedPCMReader( PCMConverter(pcmreader, sample_rate=48000, channels=pcmreader.channels, channel_mask=pcmreader.channel_mask, bits_per_sample=16)), quality=int(compression), original_sample_rate=pcmreader.sample_rate) return cls(filename) except (ValueError, IOError), err: cls.__unlink__(filename) raise EncodingError(err)
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): """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 from_pcm(cls, filename, pcmreader, compression=None, total_pcm_frames=None): """encodes a new file from PCM data takes a filename string, PCMReader object, optional compression level string and optional total_pcm_frames integer encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new M4AAudio object""" import tempfile import os import os.path from audiotools import PCMConverter from audiotools import WaveAudio from audiotools import __default_quality__ if ((compression is None) or (compression not in cls.COMPRESSION_MODES)): compression = __default_quality__(cls.NAME) tempwavefile = tempfile.NamedTemporaryFile(suffix=".wav", delete=False) tempwave_name = tempwavefile.name try: if pcmreader.sample_rate > 96000: tempwave = WaveAudio.from_pcm( tempwave_name, PCMConverter(pcmreader, sample_rate=96000, channels=pcmreader.channels, channel_mask=pcmreader.channel_mask, bits_per_sample=pcmreader.bits_per_sample), total_pcm_frames=total_pcm_frames) else: tempwave = WaveAudio.from_pcm( tempwave_name, pcmreader, total_pcm_frames=total_pcm_frames) cls.__from_wave__(filename, tempwave.filename, compression) return cls(filename) finally: tempwavefile.close() if os.path.isfile(tempwave_name): os.unlink(tempwave_name)
def from_pcm(cls, filename, pcmreader, compression=None, total_pcm_frames=None): """encodes a new file from PCM data takes a filename string, PCMReader object, optional compression level string and optional total_pcm_frames integer encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new MP3Audio object""" from audiotools import (PCMConverter, BufferedPCMReader, ChannelMask, __default_quality__, EncodingError) from audiotools.encoders import encode_mp3 if (((compression is None) or (compression not in cls.COMPRESSION_MODES))): compression = __default_quality__(cls.NAME) try: encode_mp3( filename, BufferedPCMReader( PCMConverter(pcmreader, sample_rate=pcmreader.sample_rate, channels=min(pcmreader.channels, 2), channel_mask=ChannelMask.from_channels( min(pcmreader.channels, 2)), bits_per_sample=16)), compression) return MP3Audio(filename) except (ValueError, IOError), err: cls.__unlink__(filename) raise EncodingError(str(err))
def from_pcm(cls, filename, pcmreader, compression=None, total_pcm_frames=None): """encodes a new file from PCM data takes a filename string, PCMReader object, optional compression level string and optional total_pcm_frames integer encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new M4AAudio object""" import subprocess import os from audiotools import PCMConverter from audiotools import transfer_data from audiotools import transfer_framelist_data from audiotools import ignore_sigint from audiotools import EncodingError from audiotools import DecodingError from audiotools import ChannelMask from audiotools import __default_quality__ if ((compression is None) or (compression not in cls.COMPRESSION_MODES)): compression = __default_quality__(cls.NAME) if pcmreader.channels > 2: pcmreader = PCMConverter(pcmreader, sample_rate=pcmreader.sample_rate, channels=2, channel_mask=ChannelMask.from_channels(2), bits_per_sample=pcmreader.bits_per_sample) # faac requires files to end with .m4a for some reason if not filename.endswith(".m4a"): import tempfile actual_filename = filename tempfile = tempfile.NamedTemporaryFile(suffix=".m4a") filename = tempfile.name else: actual_filename = tempfile = None sub = subprocess.Popen( [ BIN['faac'], "-q", compression, "-P", "-R", str(pcmreader.sample_rate), "-B", str(pcmreader.bits_per_sample), "-C", str(pcmreader.channels), "-X", "-o", filename, "-" ], stdin=subprocess.PIPE, stderr=subprocess.DEVNULL if hasattr(subprocess, "DEVNULL") else open(os.devnull, "wb"), stdout=subprocess.DEVNULL if hasattr(subprocess, "DEVNULL") else open(os.devnull, "wb"), preexec_fn=ignore_sigint) # Note: faac handles SIGINT on its own, # so trying to ignore it doesn't work like on most other encoders. try: if total_pcm_frames is not None: from audiotools import CounterPCMReader pcmreader = CounterPCMReader(pcmreader) transfer_framelist_data(pcmreader, sub.stdin.write) if ((total_pcm_frames is not None) and (total_pcm_frames != pcmreader.frames_written)): from audiotools.text import ERR_TOTAL_PCM_FRAMES_MISMATCH raise EncodingError(ERR_TOTAL_PCM_FRAMES_MISMATCH) except (ValueError, IOError) as err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise EncodingError(str(err)) except Exception: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise sub.stdin.close() if sub.wait() == 0: if tempfile is not None: filename = actual_filename f = open(filename, 'wb') tempfile.seek(0, 0) transfer_data(tempfile.read, f.write) f.close() tempfile.close() return M4AAudio(filename) else: if tempfile is not None: tempfile.close() raise EncodingError(u"unable to write file with faac")
def from_pcm(cls, filename, pcmreader, compression=None, total_pcm_frames=None): """encodes a new file from PCM data takes a filename string, PCMReader object optional compression level string, and optional total_pcm_frames integer encodes a new audio file from pcmreader's data at the given filename with the specified compression level and returns a new AudioFile-compatible object specifying total_pcm_frames, when the number is known in advance, may allow the encoder to work more efficiently but is never required """ import bisect import os import subprocess from audiotools import __default_quality__ from audiotools import transfer_framelist_data from audiotools import EncodingError from audiotools import PCMConverter from audiotools import ChannelMask 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, 24): from audiotools import UnsupportedBitsPerSample raise UnsupportedBitsPerSample(filename, pcmreader.bits_per_sample) if total_pcm_frames is not None: from audiotools import CounterPCMReader counter_reader = CounterPCMReader(pcmreader) else: counter_reader = pcmreader pcmreader = PCMConverter( counter_reader, sample_rate=[8000, 8000, 16000, 32000][bisect.bisect([8000, 16000, 32000], 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] sub = subprocess.Popen( [BIN['speexenc'], '--quality', str(compression), '--rate', str(pcmreader.sample_rate), '--le'] + \ BITS_PER_SAMPLE + \ CHANNELS + \ ['-', filename], stdin=subprocess.PIPE, stderr=subprocess.DEVNULL if hasattr(subprocess, "DEVNULL") else open(os.devnull, "wb")) try: transfer_framelist_data(pcmreader, sub.stdin.write) except (IOError, ValueError) as err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise EncodingError(str(err)) except Exception as err: sub.stdin.close() sub.wait() cls.__unlink__(filename) raise err sub.stdin.close() if sub.wait() == 0: if ((total_pcm_frames is None) or (total_pcm_frames == counter_reader.frames_written)): return SpeexAudio(filename) else: from audiotools.text import ERR_TOTAL_PCM_FRAMES_MISMATCH cls.__unlink__(filename) raise EncodingError(ERR_TOTAL_PCM_FRAMES_MISMATCH) else: raise EncodingError(u"unable to encode file with speexenc")
def from_pcm(cls, filename, pcmreader, compression=None, total_pcm_frames=None): from audiotools import __default_quality__ from audiotools import PCMConverter from audiotools import ChannelMask from audiotools.encoders import encode_mpc 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, 24}: from audiotools import UnsupportedBitsPerSample pcmreader.close() raise UnsupportedBitsPerSample(filename, pcmreader.bits_per_sample) if pcmreader.sample_rate in (32000, 37800, 44100, 48000): sample_rate = pcmreader.sample_rate if total_pcm_frames is not None: from audiotools import CounterPCMReader pcmreader = CounterPCMReader(pcmreader) else: from bisect import bisect sample_rate = [32000, 32000, 37800, 44100, 48000][bisect([32000, 37800, 44100, 4800], pcmreader.sample_rate)] total_pcm_frames = None try: encode_mpc( filename, PCMConverter(pcmreader, sample_rate=sample_rate, channels=min(pcmreader.channels, 2), channel_mask=int( ChannelMask.from_channels( min(pcmreader.channels, 2))), bits_per_sample=16), float(compression), total_pcm_frames if (total_pcm_frames is not None) else 0) # ensure PCM frames match, if indicated if ((total_pcm_frames is not None) and (total_pcm_frames != pcmreader.frames_written)): from audiotools.text import ERR_TOTAL_PCM_FRAMES_MISMATCH from audiotools import EncodingError raise EncodingError(ERR_TOTAL_PCM_FRAMES_MISMATCH) return MPCAudio(filename) except (IOError, ValueError) as err: from audiotools import EncodingError cls.__unlink__(filename) raise EncodingError(str(err)) except Exception: cls.__unlink__(filename) raise finally: pcmreader.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))