Changeset 1683

Show
Ignore:
Timestamp:
10/11/09 14:03:41 (11 years ago)
Author:
arnonym
Message:

Kind of a usable panner. In theory this should allow panning several sources to several sinks. In practice only mono-to-stereo and stereo-to-stereo is currently possible. Not because of the panner but because of the way it works in the matrixmixer. Will change that soon.

One of the current draw-backs is that I am using numpy. Standard pythons matrix handling doesn't seem so good.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/support/mixer-qt4/ffado/widgets/matrixmixer.py

    r1670 r1683  
    2020 
    2121from PyQt4 import QtGui, QtCore, Qt 
    22 import dbus 
     22import dbus, numpy 
     23 
     24from ffado.widgets.ntompanner import N2MPanner 
    2325 
    2426import logging 
     
    3739        self.outputs = [] 
    3840 
    39         self.inputbalance = QtGui.QSlider(Qt.Qt.Horizontal, self) 
    40         self.inputbalance.setRange(-100, 100) 
    41         self.connect(self.inputbalance, QtCore.SIGNAL("valueChanged(int)"), self.valuesChanged) 
    42  
    43         self.outputbalance = QtGui.QSlider(Qt.Qt.Horizontal, self) 
    44         self.outputbalance.setRange(-100, 100) 
    45         self.connect(self.outputbalance, QtCore.SIGNAL("valueChanged(int)"), self.valuesChanged) 
    46  
    4741        self.fader = QtGui.QDial(self) 
    4842        self.fader.setRange(0,pow(2,16)-1) 
     
    5246        self.setLayout(self.layout) 
    5347 
    54         self.layout.addWidget(self.inputbalance, 0, 0) 
    55         self.layout.addWidget(self.fader, 1, 0) 
    56         self.layout.addWidget(self.outputbalance, 2, 0) 
     48        self.layout.addWidget(self.fader, 0, 0) 
    5749 
    5850        self.addInputs(inputs) 
     
    6052 
    6153    def valuesChanged(self): 
     54        #log.debug("MixerNode.valuesChanged") 
    6255        fader = self.fader.value() 
    63         values = [] 
    64         while len(values) < len(self.inputs): 
    65             tmp = [] 
    66             while len(tmp) < len(self.outputs): 
    67                 tmp.append(fader) 
    68             values.append(tmp) 
    69         if len(self.inputs) == len(self.outputs): 
    70             for i in range(len(self.inputs)): 
    71                 for j in range(len(self.outputs)): 
    72                     values[i][j] *= (i==j) 
    73         if len(self.outputs) == 2: 
    74             v = self.outputbalance.value() / 100.0 
    75             left = 1.0 
    76             right = 1.0 
    77             if v > 0: 
    78                 left = 1.0 - v 
    79             if v < 0: 
    80                 right = 1.0 + v 
    81             for row in values: 
    82                 row[0] *= left 
    83                 row[1] *= right 
    84         if len(self.inputs) == 2: 
    85             v = self.inputbalance.value() / 100.0 
    86             left = 1.0 
    87             right = 1.0 
    88             if v > 0: 
    89                 left = 1.0 - v 
    90             if v < 0: 
    91                 right = 1.0 + v 
    92             for i in range(len(self.outputs)): 
    93                 values[0][i] *= left 
    94                 values[1][i] *= right 
     56        values = numpy.ones((1, len(self.inputs))) 
     57        if len(self.outputs) > 1: 
     58            values = self.panner.values 
     59            if values.size == 0: 
     60                return 
     61            values = numpy.minimum(values, 2) 
     62            values = 1 - numpy.power(values/2, 2) 
     63        #print values 
     64        #print numpy.exp(-values) 
     65        values = values * fader 
     66        #print values 
    9567        ret = [] 
    9668        for i in range(len(self.inputs)): 
    9769            for j in range(len(self.outputs)): 
    98                 ret.append( (self.inputs[i], self.outputs[j], values[i][j]) ) 
     70                ret.append( (self.inputs[i], self.outputs[j], values[i,j]) ) 
    9971        #print ret 
    10072        self.emit(QtCore.SIGNAL("valueChanged"), ret) 
     
    12597 
    12698    def checkWidgets(self): 
    127         if len(self.inputs)>1: 
    128             self.inputbalance.show(
    129         else: 
    130             self.inputbalance.hide(
    131         if len(self.outputs)>1
    132             self.outputbalance.show(
    133         else: 
    134             self.outputbalance.hide(
     99        if not hasattr(self, "panner") and len(self.outputs)>1: 
     100            self.panner = N2MPanner(self
     101            self.layout.addWidget(self.panner, 1, 0) 
     102            self.connect(self.panner, QtCore.SIGNAL("valuesChanged"), self.valuesChanged
     103        if hasattr(self, "panner")
     104            self.panner.setVisible(len(self.outputs)>1
     105            self.panner.setNumberOfSources(len(self.inputs)) 
     106            self.panner.setNumberOfSinks(len(self.outputs)
    135107        if len(self.inputs) and len(self.outputs): 
    136108            valuematrix = [] 
     
    276248 
    277249    def valueChanged(self, n): 
    278         log.debug("MatrixNode.valueChanged( %s )" % str(n)) 
     250        #log.debug("MatrixNode.valueChanged( %s )" % str(n)) 
    279251        for tmp in n: 
    280252            self.interface.setValue(tmp[1], tmp[0], tmp[2]) 
  • trunk/libffado/support/mixer-qt4/ffado/widgets/ntompanner.py

    r1680 r1683  
    2020 
    2121from PyQt4 import QtGui, QtCore, Qt 
    22 import dbus, math 
     22import dbus, math, numpy 
    2323 
    2424import logging 
    2525log = logging.getLogger("widgets") 
    2626 
    27 percentage = 0.2 
     27percentage = 0.3 
    2828circlerect = QtCore.QRectF(-percentage/2, -percentage/2, percentage, percentage) 
    2929 
     
    4848            value = self.parent.nearestSink(value.toPointF()) 
    4949        if change == QtGui.QGraphicsItem.ItemPositionHasChanged: 
    50             self.parent.sourcePositionChanged(self.number, value.toPointF()
     50            self.parent.sourcePositionChanged(self.number
    5151        return QtGui.QGraphicsEllipseItem.itemChange(self, change, value) 
    5252 
     
    6464        self.view.setScene(self.scene) 
    6565 
    66         self.scene.addEllipse( QtCore.QRectF(-1,-1,2,2), QtGui.QPen(self.palette().color(QtGui.QPalette.Window).darker() ) ) 
     66        self.scene.addEllipse( QtCore.QRectF(-1,-1,2,2), QtGui.QPen(self.palette().color(QtGui.QPalette.Window).darker() ) ).setZValue(-1) 
    6767 
    6868        self.pen = QtGui.QPen(self.palette().color(QtGui.QPalette.Window).darker()) 
    6969        #pen.setWidthF(0.01) 
    7070 
     71        self.sources = [] 
    7172        self.sinks = [] 
    72         self.values = [ [], [] ] 
    73         print self.values 
    74  
    75         self.scene.addItem(PannerSource(0,self)) 
    76         self.scene.addItem(PannerSource(1,self)) 
     73        self.values = numpy.array(numpy.float) 
     74        #print self.values.flags 
     75        #print self.values 
    7776 
    7877        #self.updateGeometry() 
     
    8079 
    8180    def setNumberOfSinks(self, sinknr): 
    82         print "N2MPanner.setNumberOfSinks() sinknr=%i len(self.sinks)=%i" % (sinknr,len(self.sinks)) 
    83         while len(self.sinks) > 0: 
     81        while len(self.sinks) > sinknr: 
    8482            self.sinks[-1].setParentItem(None) 
    8583            del self.sinks[-1] 
    86         print "N2MPanner.setNumberOfSinks() sinknr=%i len(self.sinks)=%i" % (sinknr,len(self.sinks)) 
    8784        while len(self.sinks) < sinknr: 
    8885            c = self.scene.addEllipse(circlerect, self.pen) 
     
    9087            self.sinks.append(c) 
    9188        for i in range(sinknr): 
    92             degree = 2*math.pi/sinknr * i 
     89            degree = 2*math.pi/sinknr 
    9390            self.sinks[i].setPos(math.cos(degree), math.sin(degree)) 
    9491        self.update() 
    95         print "N2MPanner.setNumberOfSinks() sinknr=%i len(self.sinks)=%i" % (sinknr,len(self.sinks)) 
     92        self.values.resize((len(self.sources), len(self.sinks))) 
     93        self.sourcePositionChanged(range(len(self.sources))) 
    9694 
     95    def setNumberOfSources(self, sourcenr): 
     96        while len(self.sources) > sourcenr: 
     97            self.sources[-1].setParentItem(None) 
     98            del self.sources[-1] 
     99        while len(self.sources) < sourcenr: 
     100            s = PannerSource(len(self.sources), self) 
     101            self.scene.addItem(s) 
     102            self.sources.append(s) 
     103        self.values.resize((len(self.sources), len(self.sinks))) 
     104        self.sourcePositionChanged(range(len(self.sources))) 
    97105 
    98106    def distance(self, p1, p2): 
    99107        return math.sqrt( math.pow(p1.x()-p2.x(), 2) + math.pow(p1.y()-p2.y(), 2) ) 
    100108 
    101     def sourcePositionChanged(self, number, point): 
    102         print "N2MPanner.sourcePositionChanged( %i, [%g, %g] )" % (number, point.x(), point.y()) 
    103         for sink in self.sinks: 
    104             index = self.sinks.index(sink) 
    105             #self.values[number].extend(index) 
    106             while len(self.values[number]) < index+1: 
    107                 self.values[number].append(0) 
    108             self.values[number][index] = self.distance(point, sink.pos()) 
    109             #print " distance to sink(%g, %g) is %g" % (sink.x(), sink.y(), self.distance(point, sink.pos())) 
    110         print self.values 
     109    def sourcePositionChanged(self, number): 
     110        if not isinstance(number, list): 
     111            number = [number] 
     112        #print "N2MPanner.sourcePositionChanged( %s )" % str(number) 
     113        for i in number: 
     114            for sink in self.sinks: 
     115                j = self.sinks.index(sink) 
     116                self.values[i,j] = self.distance(self.sources[i].pos(), sink.pos()) 
     117                #print " distance to sink(%g, %g) is %g" % (sink.x(), sink.y(), self.distance(self.sources[number].pos(), sink.pos())) 
     118        #print self.values 
     119        self.emit(QtCore.SIGNAL("valuesChanged")) 
    111120 
    112121    def nearestSink(self, point): 
     
    129138    l = QtGui.QVBoxLayout(w) 
    130139 
    131     s = QtGui.QSpinBox(w) 
    132     s.setRange(1,10) 
    133     l.addWidget(s) 
     140    s1 = QtGui.QSpinBox(w) 
     141    s1.setRange(1,10) 
     142    l.addWidget(s1) 
     143 
     144    s2 = QtGui.QSpinBox(w) 
     145    s2.setRange(1,10) 
     146    l.addWidget(s2) 
    134147 
    135148    p = N2MPanner(w) 
    136149    p.setNumberOfSinks(1) 
    137     QtCore.QObject.connect(s, QtCore.SIGNAL("valueChanged(int)"), p.setNumberOfSinks) 
     150    p.setNumberOfSources(1) 
     151    QtCore.QObject.connect(s1, QtCore.SIGNAL("valueChanged(int)"), p.setNumberOfSinks) 
     152    QtCore.QObject.connect(s2, QtCore.SIGNAL("valueChanged(int)"), p.setNumberOfSources) 
    138153    l.addWidget(p) 
    139154