Ejemplo n.º 1
0
    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'])
Ejemplo n.º 2
0
    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'])
Ejemplo n.º 3
0
    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'])
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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))
Ejemplo n.º 8
0
    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))
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
    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))
Ejemplo n.º 11
0
    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")
Ejemplo n.º 12
0
    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")
Ejemplo n.º 13
0
    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()
Ejemplo n.º 14
0
    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))