Esempio n. 1
0
    def __init__(self, kind, qsize=16, **kwargs):
        callback = _ffi.addressof(_lib, 'callback')

        self._action_q = RingBuffer(_ffi.sizeof('struct action*'), qsize)
        self._result_q = RingBuffer(_ffi.sizeof('struct action*'), qsize)
        self._state = _ffi.new(
            'struct state*',
            dict(
                input_channels=0,
                output_channels=0,
                samplerate=0,
                action_q=self._action_q._ptr,
                result_q=self._result_q._ptr,
                actions=_ffi.NULL,
            ))
        _sd._StreamBase.__init__(self,
                                 kind=kind,
                                 dtype='float32',
                                 callback=callback,
                                 userdata=self._state,
                                 **kwargs)
        self._state.samplerate = self.samplerate

        self._actions = set()
        self._temp_action_ptr = _ffi.new('struct action**')
Esempio n. 2
0
    def record_ringbuffer(self,
                          ringbuffer,
                          channels=None,
                          start=0,
                          allow_belated=True):
        """Send a `RingBuffer` to the callback to be recorded into.

        By default, the number of channels is obtained from the ring
        buffer's :attr:`~RingBuffer.elementsize`.

        """
        samplesize, _ = _sd._split(self.samplesize)
        if channels is None:
            channels = ringbuffer.elementsize // samplesize
        channels, mapping = self._check_channels(channels, 'input')
        if ringbuffer.elementsize != samplesize * channels:
            raise ValueError('Incompatible elementsize')
        action = _ffi.new(
            'struct action*',
            dict(
                type=RECORD_RINGBUFFER,
                allow_belated=allow_belated,
                requested_time=start,
                ringbuffer=ringbuffer._ptr,
                total_frames=ULONG_MAX,
                channels=channels,
                mapping=mapping,
            ))
        self._enqueue(action)
        return action
Esempio n. 3
0
    def stats(self):
        """Get over-/underflow statistics from an *inactive* stream.

        To get statistics from an :attr:`~sounddevice.Stream.active`
        stream, use `fetch_and_reset_stats()`.

        """
        if self.active:
            raise RuntimeError('Accessing .stats on an active stream')
        return _ffi.new('struct stats*', self._state.stats)
Esempio n. 4
0
    def fetch_and_reset_stats(self, time=0, allow_belated=True):
        """Fetch and reset over-/underflow statistics of the stream.

        """
        action = _ffi.new('struct action*', dict(
            type=FETCH_AND_RESET_STATS,
            allow_belated=allow_belated,
            requested_time=time,
        ))
        self._enqueue(action)
        return action
Esempio n. 5
0
    def record_buffer(self, buffer, channels, start=0, allow_belated=True):
        """Send a buffer to the callback to be recorded into.

        """
        channels, mapping = self._check_channels(channels, 'input')
        buffer = _ffi.from_buffer(buffer)
        samplesize, _ = _sd._split(self.samplesize)
        action = _ffi.new('struct action*', dict(
            type=RECORD_BUFFER,
            allow_belated=allow_belated,
            requested_time=start,
            buffer=_ffi.cast('float*', buffer),
            total_frames=len(buffer) // channels // samplesize,
            channels=channels,
            mapping=mapping,
        ))
        self._enqueue(action)
        return action
Esempio n. 6
0
    def cancel(self, action, time=0, allow_belated=True):
        """Initiate stopping a running action.

        This creates another action that is sent to the callback in
        order to stop the given *action*.

        This function typically returns before the *action* is actually
        stopped.  Use `wait()` (on either one of the two actions) to
        wait until it's done.

        """
        cancel_action = _ffi.new('struct action*', dict(
            type=CANCEL,
            allow_belated=allow_belated,
            requested_time=time,
            action=action,
        ))
        self._enqueue(cancel_action)
        return cancel_action
Esempio n. 7
0
    def play_buffer(self, buffer, channels, start=0, allow_belated=True):
        """Send a buffer to the callback to be played back.

        After that, the *buffer* must not be written to anymore.

        """
        channels, mapping = self._check_channels(channels, 'output')
        buffer = _ffi.from_buffer(buffer)
        _, samplesize = _sd._split(self.samplesize)
        action = _ffi.new('struct action*', dict(
            type=PLAY_BUFFER,
            allow_belated=allow_belated,
            requested_time=start,
            buffer=_ffi.cast('float*', buffer),
            total_frames=len(buffer) // channels // samplesize,
            channels=channels,
            mapping=mapping,
        ))
        self._enqueue(action)
        return action