File size: 3,238 Bytes
c051af2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from Queue import PriorityQueue, Queue, Full

import numpy as np

from dspy.generator import Generator
from dspy.lib import rechannel, t2f


class Player(Generator):
    def __init__(self, sequence=[], channels=2, live=True, loop=False, clip=True, max_size=0):
        Generator.__init__(self)
        self.max_size = max_size
        self._generators = PriorityQueue(max_size)
        self._finished = Queue()
        self._gain = 0.1
        self._live = live
        self._length_cache = max([f+g.length() for (f, g) in sequence] + [0])
        self.loop = loop
        self.clip = clip
        self.num_channels = channels

        self.num_gens = 0

        if sequence:
            for (f, g) in sequence:
                self._append_gen(f, g)

        if live:
            assert(not loop)


        self.auto_reset = loop

    def _append_gen(self, frame, gen):
        try:
            self._generators.put((t2f(frame), gen), False)
        except Full:
            print('Too many generators to append another')
            return

    def add(self, gen, time=None):
        if time is None:
            frame = self.frame
        else:
            frame = t2f(time)
        self._length_cache = max(self._length_cache, gen.length() + frame)

        if self.num_gens < self.max_size or self.max_size == 0:
            self.num_gens += 1
            self._append_gen(frame, gen)

    def _reset(self):
        if self._live:
            raise Exception('Cannot reset if Player is live')

        sequence = []
        while not self._finished.empty():
            frame, gen = self._finished.get()
            gen.reset()
            sequence.append((frame, gen))

        while not self._generators.empty():
            frame, gen = self._generators.get()
            gen.reset()
            sequence.append((frame, gen))

        for frame, gen in sequence:
            self._append_gen(frame, gen)

    def _length(self):
        if self._live:
            return float('inf')

        return self._length_cache

    @property
    def gain(self):
        return self._gain

    @gain.setter
    def gain(self, value):
        self._gain = np.clip(value, 0, 1)

    def _generate(self, frame_count):
        output = np.zeros(frame_count * self.num_channels, dtype=np.float32)
        not_done = []
        while not self._generators.empty():
            frame, gen = self._generators.get()
            if frame > self.frame + frame_count:
                not_done.append((frame, gen))
                break

            delay = 0
            if frame > self.frame:
                delay = frame - self.frame

            signal, continue_flag = gen.generate(frame_count - delay)
            signal = rechannel(signal, gen.num_channels, self.num_channels)
            output[delay * self.num_channels:] += signal
            if continue_flag:
                not_done.append((frame, gen))
            else:
                if not self._live:
                    self._finished.put((frame, gen))
                self.num_gens -= 1

        for frame, gen in not_done:
            self._append_gen(frame, gen)

        output *= self.gain
        if self.clip:
            output = np.clip(output, -1, 1)
        return output