Example #1
0
    def refill(self, write_size):
        if _debug:
            print('refill', write_size)

        self._lock.acquire()

        while write_size > self._min_buffer_size:
            audio_data = self.source_group.get_audio_data(write_size)
            if not audio_data:
                self._eos = True
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_eos')))
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_source_group_eos')))
                break

            for event in audio_data.events:
                cursor = self._write_cursor + event.timestamp * \
                    self.source_group.audio_format.bytes_per_second
                self._events.append((cursor, event))

            context.lock()
            buffer = bufferPool.getBuffer(self._al_source)
            al.alBufferData(buffer,
                            self._al_format,
                            audio_data.data,
                            audio_data.length,
                            self.source_group.audio_format.sample_rate)
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print(("BUFFER DATA ERROR: " + str(error)))
            al.alSourceQueueBuffers(self._al_source, 1, ctypes.byref(buffer))
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print(("QUEUE BUFFER ERROR: " + str(error)))
            context.unlock()

            self._write_cursor += audio_data.length
            self._buffer_sizes.append(audio_data.length)
            self._buffer_timestamps.append(audio_data.timestamp)
            write_size -= audio_data.length

        # Check for underrun stopping playback
        if self._playing:
            state = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
            if state.value != al.AL_PLAYING:
                if _debug:
                    print('underrun')
                al.alSourcePlay(self._al_source)
            context.unlock()

        self._lock.release()
Example #2
0
    def refill(self, write_size):
        self.lock()
        while write_size > 0:
            if _debug:
                print 'refill, write_size =', write_size
            # Get next audio packet (or remains of last one)
            if self._next_audio_data:
                audio_data = self._next_audio_data
                self._next_audio_data = None
            else:
                audio_data = self.source_group.get_audio_data(write_size)

            # Write it, or silence if there are no more packets
            if audio_data:
                # Add events
                for event in audio_data.events:
                    event_cursor = self._write_cursor + event.timestamp * \
                        self.source_group.audio_format.bytes_per_second
                    self._events.append((event_cursor, event))

                # Add timestamp (at end of this data packet)
                ts_cursor = self._write_cursor + audio_data.length
                self._timestamps.append(
                    (ts_cursor, audio_data.timestamp + audio_data.duration))

                # Write data
                if _debug:
                    print 'write', audio_data.length
                length = min(write_size, audio_data.length)
                self.write(audio_data, length)
                if audio_data.length:
                    self._next_audio_data = audio_data
                write_size -= length
            else:
                # Write silence
                if self._eos_cursor is None:
                    self._eos_cursor = self._write_cursor
                    self._events.append(
                        (self._eos_cursor, MediaEvent(0, 'on_eos')))
                    self._events.append(
                        (self._eos_cursor, MediaEvent(0,
                                                      'on_source_group_eos')))
                    self._events.sort()
                if self._write_cursor > self._eos_cursor + self._buffer_size:
                    self.stop()
                else:
                    self.write(None, write_size)
                write_size = 0

        self.unlock()
Example #3
0
    def _worker_func(self):
        thread = self._thread
        #buffered_time = 0
        eos = False
        events = self._events

        while True:
            with thread.condition:
                if thread.stopped or (eos and not events):
                    break

                # Use up "buffered" audio based on amount of time passed.
                timestamp = self.get_time()
                if _debug:
                    print 'timestamp: %r' % timestamp

                # Dispatch events
                while events and timestamp is not None:
                    if (events[0].timestamp is None
                            or events[0].timestamp <= timestamp):
                        events[0]._sync_dispatch_to_player(self.player)
                        del events[0]
                    else:
                        break

                # Calculate how much data to request from source
                secs = self._buffer_time - self._packets_duration
                bytes = secs * self.source_group.audio_format.bytes_per_second
                if _debug:
                    print 'Trying to buffer %d bytes (%r secs)' % (bytes, secs)

                while bytes > self._min_update_bytes and not eos:
                    # Pull audio data from source
                    audio_data = self.source_group.get_audio_data(int(bytes))
                    if not audio_data and not eos:
                        events.append(MediaEvent(timestamp, 'on_eos'))
                        events.append(
                            MediaEvent(timestamp, 'on_source_group_eos'))
                        eos = True
                        break

                    # Pretend to buffer audio data, collect events.
                    if self._playing and not self._packets:
                        self._timestamp_time = time.time()
                    self._packets.append(
                        SilentAudioPacket(audio_data.timestamp,
                                          audio_data.duration))
                    self._packets_duration += audio_data.duration
                    for event in audio_data.events:
                        event.timestamp += audio_data.timestamp
                        events.append(event)
                    events.extend(audio_data.events)
                    bytes -= audio_data.length

                sleep_time = self._sleep_time
                if not self._playing:
                    sleep_time = None
                elif events and events[0].timestamp and timestamp:
                    sleep_time = min(sleep_time,
                                     events[0].timestamp - timestamp)

                if _debug:
                    print 'SilentAudioPlayer(Worker).sleep', sleep_time
                thread.sleep(sleep_time)