示例#1
0
    def __init__(self, options=None):
        """Updates self.init_options dictionary with option values, creating the dictionary if it doesn't exist."""

        super(sigprocbase, self).__init__()

        self.original_options = options

        if not hasattr(self, 'init_options'):
            self.init_options = attrdict()
        init_options = self.init_options

        if not hasattr(self, 'init_args'):
            self.init_args = list()
        init_args = self.init_args

        if options is None:
            return

        if isinstance(options, str):
            options = options.split()

        if isinstance(options, (list, tuple)):
            # put assignments in the dictionary
            init_options.update(option.split('=') for option in options if option.count('=') == 1)
            # append all others onto the list
            init_args.extend(option for option in options if option.count('=') != 1)
        elif isinstance(options, dict):
            init_options.update(options)
        else:
            raise ValueError("expected options to be an instance of str, tuple, list, or dict, but got %r" %(type(options).__name__,))

        if init_options.has_key('serial_version'):
            v = int(init_options['serial_version'])
            self.check_serial_version(v)
示例#2
0
    def __init__(self, *_):
        super(Sliding, self).__init__(*_)

        self.signal = attrdict()

        # usec
        self.window = 25000
        self.hop = self.window // 3
示例#3
0
    def __init__(self, *_):
        super(Sliding, self).__init__(*_)

        self.signal = attrdict()

        # usec
        self.window = 25000
        self.hop = self.window // 3
示例#4
0
 def __init__(self, length, add, remove):
     stats = builtin.attrdict((
         ('num_added', 0),
         ('num_removed', 0),
         ('max_queued', 0),
         ('min_timestamp', None),
         ('max_timestamp', None),
         ('prev_timestamp', None),
         ))
     self._data = length, collections.deque(), add, remove, stats
示例#5
0
 def state(self):
     result = attrdict()
     STATE = self._scan('STATE')
     UINT = self._scan('UINT')
     result.statenum = atoi(UINT)
     mean = self.mean()
     result.mean = mean
     var = self.var()
     result.var = var
     if self._peek('GCONST', 'STATE', 'TRANSP') == 'GCONST':
         gconst = self.gconst()
         result.gconst = gconst
     return ('state', result)
示例#6
0
 def hmm(self):
     result = attrdict()
     if self._peek('BEGINHMM', 'HMMMACRO') == 'HMMMACRO':
         hmmdecl = self.hmmdecl()
         result.decl = hmmdecl
     BEGINHMM = self._scan('BEGINHMM')
     numstates = self.numstates()
     result.numstates = numstates
     result.states = []
     while self._peek('STATE', 'TRANSP') == 'STATE':
         state = self.state()
         result.states.append(state)
     transp = self.transp()
     result.transp = transp
     ENDHMM = self._scan('ENDHMM')
     return ('HMM', result)
示例#7
0
    def __init__(self, options=None):
        """Updates self.init_options dictionary with option values, creating the dictionary if it doesn't exist."""

        super(sigprocbase, self).__init__()

        self.original_options = options

        if not hasattr(self, 'init_options'):
            self.init_options = attrdict()
        init_options = self.init_options

        if not hasattr(self, 'init_args'):
            self.init_args = list()
        init_args = self.init_args

        if options is None:
            return

        if isinstance(options, str):
            options = options.split()

        if isinstance(options, (list, tuple)):
            # put assignments in the dictionary
            init_options.update(
                option.split('=') for option in options
                if option.count('=') == 1)
            # append all others onto the list
            init_args.extend(option for option in options
                             if option.count('=') != 1)
        elif isinstance(options, dict):
            init_options.update(options)
        else:
            raise ValueError(
                "expected options to be an instance of str, tuple, list, or dict, but got %r"
                % (type(options).__name__, ))

        if init_options.has_key('serial_version'):
            v = int(init_options['serial_version'])
            self.check_serial_version(v)
示例#8
0
 def __init__(self, args=None):
     self.init_options = attrdict({'base': EulersNumber, 'scale': 1})
     super(Log, self).__init__(args)
     self.logbase = pow(number(self.init_options.base), 1 / number(self.init_options.scale))
示例#9
0
    def __init__(self, r, theta):
        """
        A simple two-pole system, with zeros at 1 and -1.  Argument r
        is the radius to each pole, theta is the angle in radians.  In
        the running system, you can vary r via h.set_r(new_r_value)
        for nonlinear behavior.

        >>> for y in nonlinear2pole(0.97, 0.4).process_some((.1,) * 30):
        ...   y+=15;print '-' * int(y), int(y)
        ----------------- 17
        ---------------------- 22
        ------------------------- 25
        -------------------------- 26
        -------------------------- 26
        ------------------------ 24
        -------------------- 20
        ---------------- 16
        ------------ 12
        -------- 8
        ------ 6
        ----- 5
        ------ 6
        -------- 8
        ---------- 10
        -------------- 14
        ----------------- 17
        -------------------- 20
        --------------------- 21
        ---------------------- 22
        --------------------- 21
        -------------------- 20
        ----------------- 17
        --------------- 15
        ------------ 12
        ---------- 10
        --------- 9
        --------- 9
        --------- 9
        ----------- 11
        """

        super(nonlinear2pole, self).__init__()

        def H(z):
            # print
            # print 'r', r, ' theta', theta
            zsq = z ** 2
            num = zsq - 1
            num2 = (z - 1) * (z + 1)
            # print 'num', num, num - num2
            # print 'abs(num)', abs(num), 2 * math.sin(theta)
            #print 'z', z, abs(z), ' zsq', zsq, abs(zsq)
            den = zsq - 2 * r * math.cos(theta) * z + r ** 2
            den2 = (z - r * pow(cmath.e, 1j*theta)) *  (z - r * pow(cmath.e, -1j*theta))
            # print 'den', den, den - den2

            cos2theta = math.cos(2 * theta)
            asq = 1 - cos2theta ** 2
            bsq = asq + (r - cos2theta) ** 2
            assert bsq >= 0
            den3 = abs(1 - r) * math.sqrt(bsq)
            # print 'den3', den3, abs(den) - den3
            #print 'd', d
            #return 1
            
            return num / den

        coeffs_b = 0, -1

        # XXX write set_r, and use it here
        coeffs_a = -2 * r * math.cos(theta), r * r
        coeff_k = (2 * math.sin(theta)) / (1 - r)

        # print 'coeff_k', coeff_k, ' |H(theta)|', abs(H(pow(cmath.e, 1j*theta)))

        if len(coeffs_b) > 2:
            raise ValueError("expected coeffs_b of length 2 or less, got %d" % (len(coeffs_b),))
        if len(coeffs_a) > 2:
            raise ValueError("expected coeffs_a of length 2 or less, got %d" % (len(coeffs_a),))

        coeffs_b = tuple(islice(chain(coeffs_b, repeat(0)), 2))
        coeffs_a = tuple(islice(chain(coeffs_a, repeat(0)), 2))
        self.coeff_k = coeff_k
        self.ba = tuple(izip(coeffs_b, coeffs_a))
        assert len(self.ba) == 2
        self.deque = deque((0, 0))
        
        self.data = self.coeff_k, self.ba, self.deque

        def senderator(coeffs_a, coeffs_b, coeff_k, signal, recipient=None):
            a1, a2 = coeffs_a
            b1, b2 = coeffs_b
            k = coeff_k

            # so we can use 'is' comparisons
            zero = 0
            a1 = a1 or zero
            a2 = a2 or zero
            b1 = b1 or zero
            b2 = b2 or zero
            w1, w2 = reset = zero, zero
            hasattr = signal.hasattr
            result = None

            while True:
                x = yield result
                result = None

                if x is signal:
                    if hasattr.get_recipient:
                        result = recipient
                    if hasattr.set_recipient:
                        recipient = signal.set_recipient
                    if hasattr.get_state:
                        result = w1, w2
                    if hasattr.set_state:
                        w1, w2 = signal.set_state
                    if hasattr.reset:
                        w1, w2 = reset
                    continue

                w = k * x
                if a1 is not zero: w -= a1 * w1
                if a2 is not zero: w -= a2 * w2

                y = w
                if b1 is not zero: y += b1 * w1
                if b2 is not zero: y += b2 * w2

                w2 = w1
                w1 = w

                if recipient is not None:
                    recipient(y)

        self.signal = attrdict()
        self.send = senderator(coeffs_a, coeffs_b, coeff_k, self.signal).send
        self.send(None)
示例#10
0
    def __init__(self, coeffs_a, coeffs_b, coeff_k=1):
        """
        Construct a canonic Type II filter that implements the
        (inhomogeneous) second-order difference equation:

          y[n] + a1 * y[n-1] + a2 * y[n-2]  =  k * (x[n] + b1 * x[n-1] + b2 * x[n-2])
        
        generating the solution y[n] given input sequence x[n]:
        
          y[n]  =  -1 * (a1 * y[n-1] + a2 * y[n-2])  +  k * (x[n] + b1 * x[n-1] + b2 * x[n-2])  

        The 'coeffs_a' is a sequence of zero to two IIR coefficients,
        'a' in the above.  The 'coeffs_b' is a sequence of zero to two
        FIR coefficients, 'b' in the above.  In these two sequences,
        missing trailing coefficients are treated as having value 0.
        The optional 'coeff_k' argument is the overall scaling factor
        that defaults to one, 'k' in the above.
        """

        super(type2stage, self).__init__()

        if len(coeffs_b) > 2:
            raise ValueError("expected coeffs_b of length 2 or less, got %d" % (len(coeffs_b),))
        if len(coeffs_a) > 2:
            raise ValueError("expected coeffs_a of length 2 or less, got %d" % (len(coeffs_a),))

        coeffs_b = tuple(islice(chain(coeffs_b, repeat(0)), 2))
        coeffs_a = tuple(islice(chain(coeffs_a, repeat(0)), 2))
        self.coeff_k = coeff_k
        self.ba = tuple(izip(coeffs_b, coeffs_a))
        assert len(self.ba) == 2
        self.deque = deque((0, 0))
        
        self.data = self.coeff_k, self.ba, self.deque

        def senderator(coeffs_a, coeffs_b, coeff_k, signal, recipient=None):
            a1, a2 = coeffs_a
            b1, b2 = coeffs_b
            k = coeff_k

            # so we can use 'is' comparisons
            zero = 0
            a1 = a1 or zero
            a2 = a2 or zero
            b1 = b1 or zero
            b2 = b2 or zero
            w1, w2 = reset = zero, zero
            hasattr = signal.hasattr
            result = None

            while True:
                x = yield result
                result = None

                if x is signal:
                    if hasattr.get_recipient:
                        result = recipient
                    if hasattr.set_recipient:
                        recipient = signal.set_recipient
                    if hasattr.get_state:
                        result = w1, w2
                    if hasattr.set_state:
                        w1, w2 = signal.set_state
                    if hasattr.reset:
                        w1, w2 = reset
                    continue

                w = k * x
                if a1 is not zero: w -= a1 * w1
                if a2 is not zero: w -= a2 * w2

                y = w
                if b1 is not zero: y += b1 * w1
                if b2 is not zero: y += b2 * w2

                w2 = w1
                w1 = w

                if recipient is not None:
                    recipient(y)

        self.signal = attrdict()
        self.send = senderator(coeffs_a, coeffs_b, coeff_k, self.signal).send
        self.send(None)
示例#11
0
def _get_sphere_fd(fileno, file_num_bytes, filename, wave_format,
                   filename_abs):
    """
    Low-level reading of NIST Sphere audio data.
    
    >>> module_dir, module_name = os.path.split(__file__)
    >>> zero_sph = os.path.join(module_dir, 'zero.sph')
    >>> shorten_sph = os.path.join(module_dir, 'shorten.sph')

    >>> with open(zero_sph, 'rb') as audio_file:
    ...   file_info, audio_info, wave = _get_sphere_fd(audio_file.fileno(), os.path.getsize(zero_sph), zero_sph, 'int16', os.path.abspath(zero_sph))

    >>> for key in sorted(file_info): print "%-24s  %r" % (key, file_info[key])
    file_item_bytes           2
    file_item_coding          'int16'
    file_sndfile_extension    'sph'
    file_sndfile_format       ''
    file_sndfile_type         'pcm SPH (NIST Sphere)'

    >>> for key in sorted(audio_info): print "%-24s  %r" % (key, audio_info[key])
    audio_num_channels        2
    audio_num_samples         128064
    audio_sample_rate         44100

    >>> print str(wave)
    [[  0  -1  -3 ..., 203 211 199]
     [  0   0  -3 ..., 225 225 221]]


    >>> with open(shorten_sph, 'rb') as audio_file:
    ...   file_info2, audio_info2, wave2 = _get_sphere_fd(audio_file.fileno(), os.path.getsize(shorten_sph), shorten_sph, 'int16', os.path.abspath(shorten_sph))

    >>> for key in sorted(file_info2): print "%-24s  %r" % (key, file_info2[key])
    file_item_bytes           2
    file_item_coding          'int16'
    file_sndfile_extension    'sph'
    file_sndfile_format       ''
    file_sndfile_type         'pcm,embedded-shorten-v2.00 SPH (NIST Sphere)'

    >>> for key in sorted(audio_info2): print "%-24s  %r" % (key, audio_info2[key])
    audio_num_channels        1
    audio_num_samples         37120
    audio_sample_rate         20000

    >>> print str(wave2)
    [[-1  1  1 ..., -4 -8 -5]]
    """

    assert wave_format is None or wave_format in wave_c_formats

    # As of 2009-04-20 see the following for NIST's underspecified
    # format description:
    #   http://ftp.cwi.nl/audio/NIST-SPHERE
    #   http://www.ldc.upenn.edu/Catalog/docs/LDC93S5/WAV_SPEC.TXT

    nist_1a = 'NIST_1A'
    header1 = read_fd_strict(fileno, 128, filename_abs)
    if not header1.startswith(nist_1a):
        raise AudioTypeError(
            "did not find %r in header of purported NIST Sphere file %r" %
            (nist_1a, filename_abs))
    nist, header_size, rest = header1.split(None, 2)
    assert nist == nist_1a

    header_size = int(header_size)
    rest += read_fd_strict(fileno, header_size - len(header1), filename_abs)

    # For now, we require the following fields:
    #   sample_count -i 128064
    #   sample_n_bytes -i 2
    #   channel_count -i 2
    #   sample_byte_format -s2 01
    #   sample_rate -i 44100
    #   sample_coding -s3 pcm
    info = builtin.attrdict()
    for line in cStringIO.StringIO(rest):
        parts = line.split()
        if not parts or parts[0][0] == ';': continue
        if parts[0] == 'end_head': break
        if len(parts) < 3:
            raise AudioTypeError(
                "expected at least three white-space-separated fields in NIST header line %r in file %r"
                % (line.strip(), filename_abs))
        field_name, field_type, field_value = line.split(None, 3)
        #print field_name, field_type, field_value
        if field_type in ('-i', '-r'):
            field_value, _, _ = field_value.partition(';')
            info[field_name] = (int
                                if field_type == '-i' else float)(field_value)
        elif field_type.startswith('-s'):
            # here we do a stricter interpretation of the spec
            prefix_len = len(field_name + ' ' + field_type + ' ')
            str_len = int(field_type[2:])
            info[field_name] = line[prefix_len:prefix_len + str_len]
        else:
            raise (AudioTypeError,
                   "unhandled field_type %r for field_name %r" %
                   (field_type, field_name))

    missing = set(
        ('sample_count', 'sample_n_bytes', 'channel_count',
         'sample_byte_format', 'sample_rate', 'sample_coding')) - set(info)
    if missing:
        raise AudioTypeError(
            "missing required header fields (%s) in NIST Sphere file %r" %
            (', '.join(sorted(missing)), filename_abs))

    # this is a blunt check against bogus data
    if info.sample_n_bytes > 2:
        raise AudioTypeError(
            "unhandled sample_n_bytes, %d, in NIST Sphere file %r" %
            (info.sample_n_bytes, filename_abs))

    audio_info = builtin.attrdict((('audio_num_channels', info.channel_count),
                                   ('audio_num_samples', info.sample_count),
                                   ('audio_sample_rate', info.sample_rate)))
    check_positive_ints(audio_info, filename_abs)
    file_info = builtin.attrdict((
        ('file_item_bytes', info.sample_n_bytes),
        ('file_item_coding', ('int' + str(8 * info.sample_n_bytes))
         if info.sample_coding.lower().startswith('pcm') else
         info.sample_coding[:4].lower()),
        ('file_sndfile_extension', 'sph'),
        ('file_sndfile_format', ''),
        ('file_sndfile_type', info.sample_coding + ' SPH (NIST Sphere)'),
    ))
    check_positive_ints(file_info, filename_abs)

    if wave_format is not None:
        args = 'sph2pipe', '-p', '-f', 'raw', filename_abs
        stdout, stderr, cmd = process.subprocess(args)
        if stderr:
            raise onyx.ExternalError(
                "unexpected stderr from command '%s': '%s'" %
                (cmd, stderr.strip()))
        num_audio_bytes = audio_info.audio_num_channels * audio_info.audio_num_samples * numpy.int16(
        ).itemsize
        if len(stdout) != num_audio_bytes:
            raise onyx.DataFormatError(
                "expected %d bytes of audio data, got %d" %
                (num_audio_bytes, len(stdout)))
        wave = numpy.fromstring(stdout, dtype=numpy.int16)
        assert wave.shape == (audio_info.audio_num_channels *
                              audio_info.audio_num_samples, )
        # reshape it, etc; then construct a new ndarray
        wave = wave.reshape((-1, audio_info.audio_num_channels)).transpose()
        wave = numpy.array(wave, dtype=wave_numpy_formats[wave_format])
        # do scaling the same way libsndfile does
        if wave_format == 'int32':
            wave <<= 16
        elif wave_format in ('float32', 'float64'):
            wave *= (1 / (1 << 15))
        assert wave.shape == (audio_info.audio_num_channels,
                              audio_info.audio_num_samples)
    else:
        wave = None

    return file_info, audio_info, wave
示例#12
0
 def __init__(self, args=None):
     self.init_options = attrdict({'base': EulersNumber, 'scale': 1})
     super(Log, self).__init__(args)
     self.logbase = pow(number(self.init_options.base),
                        1 / number(self.init_options.scale))
示例#13
0
 def stats(self):
     length, fifo, add, remove, stats = self._data
     stats = builtin.attrdict(stats)
     stats.length = length
     return stats
示例#14
0
def _get_sphere_fd(fileno, file_num_bytes, filename, wave_format, filename_abs):
    """
    Low-level reading of NIST Sphere audio data.
    
    >>> module_dir, module_name = os.path.split(__file__)
    >>> zero_sph = os.path.join(module_dir, 'zero.sph')
    >>> shorten_sph = os.path.join(module_dir, 'shorten.sph')

    >>> with open(zero_sph, 'rb') as audio_file:
    ...   file_info, audio_info, wave = _get_sphere_fd(audio_file.fileno(), os.path.getsize(zero_sph), zero_sph, 'int16', os.path.abspath(zero_sph))

    >>> for key in sorted(file_info): print "%-24s  %r" % (key, file_info[key])
    file_item_bytes           2
    file_item_coding          'int16'
    file_sndfile_extension    'sph'
    file_sndfile_format       ''
    file_sndfile_type         'pcm SPH (NIST Sphere)'

    >>> for key in sorted(audio_info): print "%-24s  %r" % (key, audio_info[key])
    audio_num_channels        2
    audio_num_samples         128064
    audio_sample_rate         44100

    >>> print str(wave)
    [[  0  -1  -3 ..., 203 211 199]
     [  0   0  -3 ..., 225 225 221]]


    >>> with open(shorten_sph, 'rb') as audio_file:
    ...   file_info2, audio_info2, wave2 = _get_sphere_fd(audio_file.fileno(), os.path.getsize(shorten_sph), shorten_sph, 'int16', os.path.abspath(shorten_sph))

    >>> for key in sorted(file_info2): print "%-24s  %r" % (key, file_info2[key])
    file_item_bytes           2
    file_item_coding          'int16'
    file_sndfile_extension    'sph'
    file_sndfile_format       ''
    file_sndfile_type         'pcm,embedded-shorten-v2.00 SPH (NIST Sphere)'

    >>> for key in sorted(audio_info2): print "%-24s  %r" % (key, audio_info2[key])
    audio_num_channels        1
    audio_num_samples         37120
    audio_sample_rate         20000

    >>> print str(wave2)
    [[-1  1  1 ..., -4 -8 -5]]
    """

    assert wave_format is None or wave_format in wave_c_formats

    # As of 2009-04-20 see the following for NIST's underspecified
    # format description:
    #   http://ftp.cwi.nl/audio/NIST-SPHERE
    #   http://www.ldc.upenn.edu/Catalog/docs/LDC93S5/WAV_SPEC.TXT

    nist_1a = 'NIST_1A'
    header1 = read_fd_strict(fileno, 128, filename_abs)
    if not header1.startswith(nist_1a):
        raise AudioTypeError("did not find %r in header of purported NIST Sphere file %r" % (nist_1a, filename_abs))
    nist, header_size, rest = header1.split(None, 2)
    assert nist == nist_1a

    header_size = int(header_size)
    rest += read_fd_strict(fileno, header_size - len(header1), filename_abs)

    # For now, we require the following fields:
    #   sample_count -i 128064
    #   sample_n_bytes -i 2
    #   channel_count -i 2
    #   sample_byte_format -s2 01
    #   sample_rate -i 44100
    #   sample_coding -s3 pcm
    info = builtin.attrdict()
    for line in cStringIO.StringIO(rest):
        parts = line.split()
        if not parts or parts[0][0] == ';': continue
        if parts[0] == 'end_head': break
        if len(parts) < 3:
            raise AudioTypeError("expected at least three white-space-separated fields in NIST header line %r in file %r" % (line.strip(), filename_abs))
        field_name, field_type, field_value = line.split(None, 3)
        #print field_name, field_type, field_value
        if field_type in ('-i', '-r'):
            field_value, _, _ = field_value.partition(';')
            info[field_name] = (int if field_type == '-i' else float)(field_value)
        elif field_type.startswith('-s'):
            # here we do a stricter interpretation of the spec
            prefix_len = len(field_name + ' ' + field_type + ' ')
            str_len = int(field_type[2:])
            info[field_name] = line[prefix_len:prefix_len+str_len]
        else:
            raise (AudioTypeError, "unhandled field_type %r for field_name %r" % (field_type, field_name))

    missing = set(('sample_count', 'sample_n_bytes', 'channel_count', 'sample_byte_format', 'sample_rate', 'sample_coding')) - set(info)
    if missing:
        raise AudioTypeError("missing required header fields (%s) in NIST Sphere file %r" % (', '.join(sorted(missing)), filename_abs))

    # this is a blunt check against bogus data
    if info.sample_n_bytes > 2:
        raise AudioTypeError("unhandled sample_n_bytes, %d, in NIST Sphere file %r" % (info.sample_n_bytes, filename_abs))

    audio_info = builtin.attrdict((('audio_num_channels', info.channel_count),
                                   ('audio_num_samples', info.sample_count),
                                   ('audio_sample_rate', info.sample_rate)))
    check_positive_ints(audio_info, filename_abs)
    file_info = builtin.attrdict((('file_item_bytes', info.sample_n_bytes),
                                  ('file_item_coding', ('int' + str(8*info.sample_n_bytes)) if info.sample_coding.lower().startswith('pcm') else info.sample_coding[:4].lower()),
                                  ('file_sndfile_extension', 'sph'),
                                  ('file_sndfile_format', ''),
                                  ('file_sndfile_type', info.sample_coding + ' SPH (NIST Sphere)'),
                                  ))
    check_positive_ints(file_info, filename_abs)

    if wave_format is not None:
        args = 'sph2pipe', '-p', '-f', 'raw', filename_abs
        stdout, stderr, cmd = process.subprocess(args)
        if stderr:
            raise onyx.ExternalError("unexpected stderr from command '%s': '%s'" % (cmd, stderr.strip()))
        num_audio_bytes = audio_info.audio_num_channels * audio_info.audio_num_samples * numpy.int16().itemsize
        if len(stdout) != num_audio_bytes:
            raise onyx.DataFormatError("expected %d bytes of audio data, got %d" % (num_audio_bytes, len(stdout)))             
        wave = numpy.fromstring(stdout, dtype=numpy.int16)
        assert wave.shape == (audio_info.audio_num_channels * audio_info.audio_num_samples,)
        # reshape it, etc; then construct a new ndarray
        wave = wave.reshape((-1, audio_info.audio_num_channels)).transpose()
        wave = numpy.array(wave, dtype=wave_numpy_formats[wave_format])
        # do scaling the same way libsndfile does
        if wave_format == 'int32':
            wave <<= 16
        elif wave_format in ('float32', 'float64'):
            wave *= (1 / (1 << 15))
        assert wave.shape == (audio_info.audio_num_channels, audio_info.audio_num_samples)
    else:
        wave = None

    return file_info, audio_info, wave
示例#15
0
def _get_audio_fd(fd, file_num_bytes, name, wave_format, full_name=None, is_mpeg=None):
    """
    Low-level reading of audio from libsndfile and mpg123 audio libraries.
    
    Test a correct error from libsndfile that sph2pipe does not catch; this is a
    small exercise of the error handling chain
    
    >>> module_dir, module_name = os.path.split(__file__)

    >>> problem_sph = os.path.join(module_dir, 'problem.sph')
    >>> with open(problem_sph, 'rb') as infile:
    ...   info3 = _get_audio_fd(infile.fileno(), os.path.getsize(problem_sph), problem_sph, None, problem_sph, False) #doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    AudioTypeError: .../cpp/liveaudio/sndfilewrap.c:... get_sndfile(): unexpected NULL from sf_open_fd: maybe not a valid sound file: '...problem.sph': SFC_GET_LOG_INFO: Length : 1104  psf->bytewidth (4) != bytes (2)  

    Also test that libsndfile notices that it cannot deal with shorten encoding;
    also a small exercise of the error handling chain

    >>> shorten_sph = os.path.join(module_dir, 'shorten.sph')
    >>> with open(shorten_sph, 'rb') as infile:
    ...   info3 = _get_audio_fd(infile.fileno(), os.path.getsize(shorten_sph), shorten_sph, None, shorten_sph, False) #doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    AudioTypeError: .../cpp/liveaudio/sndfilewrap.c:... get_sndfile(): unexpected NULL from sf_open_fd: maybe not a valid sound file: '...shorten.sph': SFC_GET_LOG_INFO: Length : 28357  *** Unknown encoding : pcm,embedded-shorten-v2.00  
    """
    assert fd >= 0, str(fd)
    assert wave_format is None or wave_format in wave_c_formats

    getter = _sndfilewrap_get_audio_fd if not is_mpeg else _mpg123wrap_get_audio_fd
    with getter(fd, name, wave_format) as ptrs:

        # get the returned strings
        info_str, casual, _ = tuple(ptr.value for ptr in ptrs)

        # populate info
        audio_info = builtin.attrdict((key, value) for key, value in parse_key_value(info_str) if key.startswith('audio'))
        check_positive_ints(audio_info, name)

        file_info = builtin.attrdict((key, value) for key, value in parse_key_value(info_str) if key.startswith('file'))
        file_info.file_sndfile_type = casual
        check_positive_ints(file_info, name, exclusions=('file_item_bytes',))

        # deal with the wave data at ptrs[-1], if any
        wave_ptr = ptrs[-1]
        assert (wave_ptr.value is None) == (wave_format is None)
        if wave_format is not None:
            # cast the void** data in wave_ptr to a C-array of the correct
            # length; then have Numpy use that data in a ctypeslib.as_array; get
            # a reshaped and transposed view (cheap); then copy to a bona-fide
            # Numpy array
            from numpy import ctypeslib
            # create a C type for the returned data
            c_array_t = wave_c_formats[wave_format] * audio_info.audio_num_samples * audio_info.audio_num_channels
            # use the returned memory
            wave = ctypeslib.as_array(cast(wave_ptr, POINTER(c_array_t)).contents)
            # reshape it, etc; then copy to a new ndarray
            wave = wave.reshape((-1, audio_info.audio_num_channels)).transpose().copy()
            # at this point we're done with the ptrs
            assert wave.shape == (audio_info.audio_num_channels, audio_info.audio_num_samples)
        else:
            wave = None

    return file_info, audio_info, wave
示例#16
0
    def __init__(self, instream,
                 stream_type=None,
                 stream_version=None,
                 no_stream_options=False,
                 header_only=False):

        if not isinstance(instream, YamldataGenerator):
            instream = YamldataGenerator(instream)
        have_filename = hasattr(instream, 'current_filename')
        if have_filename:
            self.current_filename = instream.current_filename
        stream_name = (self.current_filename if have_filename else "Yamldata stream")

        doc = instream.next()
        if (not hasattr(doc, '__len__')) or len(doc) == 0:
            raise ValueError("no header found in %s; are you sure this is a Yamldata source?" 
                             % stream_name)

        # attrdict of all the Onyx headers
        try:
            header = attrdict(doc[0])
        except:
            raise ValueError("bad header structure in %s: [%s] - are you sure this is a Yamldata source?"
                             % (stream_name, doc[0]))
            
        if len(doc) > 2:
            raise ValueError("bad document structure in %s, expected 1 or 2 sub-parts, got %d"
                             % (stream_name, len(doc)))
        # print doc

        if header_only:
            if len(doc) != 1:
                raise ValueError("bad document structure in %s, expected only a header"
                                 % stream_name)
            data = None
        else:
            if len(doc) != 2:
                raise ValueError("bad document structure in %s, expected both a header and a body"
                             % stream_name)
            data = doc[1]

        missing_headers = frozenset(self.prefix_header_names(self.required_headers)) - frozenset(header)
        if missing_headers:
            raise ValueError("missing the following required headers in %s: %s"
                             % (stream_name, (' '.join(repr(header) for header in sorted(missing_headers)))))

        invalid_headers = frozenset(header) - frozenset(self.prefix_header_names(self.valid_headers))
        if invalid_headers:
            raise ValueError("unexpected headers in %s: %s"
                             % (stream_name, (' '.join(repr(header) for header in sorted(invalid_headers)))))

        for base_name, prefixed_name in _izip(self.valid_headers, self.prefix_header_names(self.valid_headers)):
            if prefixed_name in header:
                self[base_name] = header[prefixed_name]

        # check the fields
        if self.meta_version != self.VERSION:
            raise ValueError("unexpected meta_version in %s: expected %s, got %s"
                             % (stream_name, self.VERSION, self.meta_version))
        if stream_type is not None and self.stream_type != stream_type:
            raise ValueError("unexpected stream_type in %s: expected %r, got %r"
                             % (stream_name, stream_type, self.stream_type))
        if stream_version is not None and self.stream_version != stream_version:
            raise ValueError("unexpected stream_version in %s: expected %s, got %s"
                             % (stream_name, repr(stream_version), repr(self.stream_version)))

        if no_stream_options and self.hasattr.stream_options:
            raise ValueError("unexpected presence of stream_options in header: %r" % (self.stream_options,))

        self.current_line_number = 4 + (0 if no_stream_options else 1)
        def itr():
            for line in data:
                self.current_line_contents = line
                self.current_line_number += 1
                # Note: PyYAML will implicitly convert tokens which
                # match certain regexps to their "natural" types.  The
                # effect is that if a line has only a single token
                # which can be converted to float or int, it will be
                # so converted.  Here we detect that and convert back
                # to a tuple with one string to make our output consistent.
                if type(line) != str:
                    parts = (str(line),)
                else:
                    parts = line.split()
                if not parts:
                    continue
                yield parts
        self._next = itr().next
示例#17
0
def _get_audio_fd(fd,
                  file_num_bytes,
                  name,
                  wave_format,
                  full_name=None,
                  is_mpeg=None):
    """
    Low-level reading of audio from libsndfile and mpg123 audio libraries.
    
    Test a correct error from libsndfile that sph2pipe does not catch; this is a
    small exercise of the error handling chain
    
    >>> module_dir, module_name = os.path.split(__file__)

    >>> problem_sph = os.path.join(module_dir, 'problem.sph')
    >>> with open(problem_sph, 'rb') as infile:
    ...   info3 = _get_audio_fd(infile.fileno(), os.path.getsize(problem_sph), problem_sph, None, problem_sph, False) #doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    AudioTypeError: .../cpp/liveaudio/sndfilewrap.c:... get_sndfile(): unexpected NULL from sf_open_fd: maybe not a valid sound file: '...problem.sph': SFC_GET_LOG_INFO: Length : 1104  psf->bytewidth (4) != bytes (2)  

    Also test that libsndfile notices that it cannot deal with shorten encoding;
    also a small exercise of the error handling chain

    >>> shorten_sph = os.path.join(module_dir, 'shorten.sph')
    >>> with open(shorten_sph, 'rb') as infile:
    ...   info3 = _get_audio_fd(infile.fileno(), os.path.getsize(shorten_sph), shorten_sph, None, shorten_sph, False) #doctest: +ELLIPSIS
    Traceback (most recent call last):
      ...
    AudioTypeError: .../cpp/liveaudio/sndfilewrap.c:... get_sndfile(): unexpected NULL from sf_open_fd: maybe not a valid sound file: '...shorten.sph': SFC_GET_LOG_INFO: Length : 28357  *** Unknown encoding : pcm,embedded-shorten-v2.00  
    """
    assert fd >= 0, str(fd)
    assert wave_format is None or wave_format in wave_c_formats

    getter = _sndfilewrap_get_audio_fd if not is_mpeg else _mpg123wrap_get_audio_fd
    with getter(fd, name, wave_format) as ptrs:

        # get the returned strings
        info_str, casual, _ = tuple(ptr.value for ptr in ptrs)

        # populate info
        audio_info = builtin.attrdict(
            (key, value) for key, value in parse_key_value(info_str)
            if key.startswith('audio'))
        check_positive_ints(audio_info, name)

        file_info = builtin.attrdict(
            (key, value) for key, value in parse_key_value(info_str)
            if key.startswith('file'))
        file_info.file_sndfile_type = casual
        check_positive_ints(file_info, name, exclusions=('file_item_bytes', ))

        # deal with the wave data at ptrs[-1], if any
        wave_ptr = ptrs[-1]
        assert (wave_ptr.value is None) == (wave_format is None)
        if wave_format is not None:
            # cast the void** data in wave_ptr to a C-array of the correct
            # length; then have Numpy use that data in a ctypeslib.as_array; get
            # a reshaped and transposed view (cheap); then copy to a bona-fide
            # Numpy array
            from numpy import ctypeslib
            # create a C type for the returned data
            c_array_t = wave_c_formats[
                wave_format] * audio_info.audio_num_samples * audio_info.audio_num_channels
            # use the returned memory
            wave = ctypeslib.as_array(
                cast(wave_ptr, POINTER(c_array_t)).contents)
            # reshape it, etc; then copy to a new ndarray
            wave = wave.reshape(
                (-1, audio_info.audio_num_channels)).transpose().copy()
            # at this point we're done with the ptrs
            assert wave.shape == (audio_info.audio_num_channels,
                                  audio_info.audio_num_samples)
        else:
            wave = None

    return file_info, audio_info, wave