All of lore.kernel.org
 help / color / mirror / Atom feed
* pyalsa: synchronizing queue with MIDI clock events
@ 2009-07-17 12:54 Christopher Arndt
  2009-07-20 12:31 ` Christopher Arndt
  2009-07-21 13:32 ` Clemens Ladisch
  0 siblings, 2 replies; 13+ messages in thread
From: Christopher Arndt @ 2009-07-17 12:54 UTC (permalink / raw)
  To: alsa-devel

Hi everybody,

this is my first post on this list, so please excuse me, should it not
be the right place to post this.

I started exploring programming the ALSA sequencer via the pyalsa Python
interface, i.e the alsaseq module. I wrote a small utility that reads
MIDI events from one port, filters/processes them and writes it to
another. This allows for routing by channel, note range, controller
number etc. and to filter out, replace or add MIDI events.

Now to synchronize the queue tempo to incoming MIDI clock events, to be
able implement synchronized delays or arpeggiators,  I use the method in
the code shown below. This works ok, but I notice that the measured BPM
oscillates +-1 BPM around the value displayed by the clock source (my
synth's sequencer) if I measure/average only a few (~10) ticks or do not
 round the result to an integer value.

Is this the right approach? What is a sensible number of ticks to take
into account for measurement? Should I use another reference timer than
Python's time.time() function? Is pyalsa generally suitable for this
kind of application even on older/weaker hardware (e.g. a NSLU2)?

Any comments or suggestions for improvement would be very much appreciated!


Chris


class MidiProcessor(object):

    def run(self):
        # This is simplified to only show the general logic
        while True:
            events = self.sequencer.receive_events(
                timeout=RECEIVE_TIMEOUT, maxevents=1)
            for event in events:
                if event.type == SEQ_EVENT_CLOCK:
                    self.sync_queue(event)
                else:
                    # do other MIDI processing / routing

    def sync_queue(self, event):
        """Sync queue tempo to incoming MIDI clock events."""
        # list to collect the timestamps of the last few ticks
        lt = self._last_ticks
        lt.append(time.time())
        ltlen = len(lt)
        if ltlen > 1:
            # calculate & set bpm: calculate difference between
            # the times the last few ticks were received and average
            # all results
            avg_delta = sum(
                 [y-x for x,y in zip(lt, lt[1:])]) / (ltlen-1)
            # tick length is a 24th of a quarter note
            bpm = round(60 / avg_delta / 24)
            if bpm != self.bpm:
                self.bpm = bpm
                self.sequencer.queue_tempo(self.queue,
                    tempo=int(6e7 / self.bpm), ppq=self.ppq)
        # only remember last 24 received ticks
        # (length of a quarter note)
        if ltlen > 24:
            lt.pop(0)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: synchronizing queue with MIDI clock events
  2009-07-17 12:54 pyalsa: synchronizing queue with MIDI clock events Christopher Arndt
@ 2009-07-20 12:31 ` Christopher Arndt
  2009-07-21 13:32 ` Clemens Ladisch
  1 sibling, 0 replies; 13+ messages in thread
From: Christopher Arndt @ 2009-07-20 12:31 UTC (permalink / raw)
  To: alsa-devel

No pyalsa or MIDI experts here?


Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: synchronizing queue with MIDI clock events
  2009-07-17 12:54 pyalsa: synchronizing queue with MIDI clock events Christopher Arndt
  2009-07-20 12:31 ` Christopher Arndt
@ 2009-07-21 13:32 ` Clemens Ladisch
  2009-07-21 16:20   ` Christopher Arndt
  1 sibling, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2009-07-21 13:32 UTC (permalink / raw)
  To: Christopher Arndt; +Cc: alsa-devel

Christopher Arndt wrote:
> Now to synchronize the queue tempo to incoming MIDI clock events, to be
> able implement synchronized delays or arpeggiators,  I use the method in
> the code shown below. This works ok, but I notice that the measured BPM
> oscillates +-1 BPM around the value displayed by the clock source (my
> synth's sequencer) if I measure/average only a few (~10) ticks or do not
>  round the result to an integer value.
> 
> Is this the right approach? What is a sensible number of ticks to take
> into account for measurement?

Large enough that you get a stable average, but small enough that you
can detect actual changes.

> Should I use another reference timer than Python's time.time() function?

That timer probably has a high enough resolution, but you measure the
time when your code is executed, which may be later then when the
event was actually received.

You can tell ALSA to timestamp all events that are received; just call
the snd_seq_port_info_set_timestamping() function and set a queue that
is running, then you'll get the queue's current time in each event.
This isn't implemented in pyalsa, but you can set this for a specific
connection with the queue, time_update, and time_real parameters of the
connect_ports function.

> Is pyalsa generally suitable for this kind of application even on
> older/weaker hardware (e.g. a NSLU2)?

The biggest problem is probably scheduling delays, so I guess using
Python instead of C should not add any noticeable delay.


Best regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: synchronizing queue with MIDI clock events
  2009-07-21 13:32 ` Clemens Ladisch
@ 2009-07-21 16:20   ` Christopher Arndt
  2009-07-31 18:26     ` pyalsa: SeqEvent.time strangeness (Was: synchronizing queue with MIDI clock events) Christopher Arndt
  0 siblings, 1 reply; 13+ messages in thread
From: Christopher Arndt @ 2009-07-21 16:20 UTC (permalink / raw)
  To: alsa-devel

Clemens Ladisch schrieb:
> Christopher Arndt wrote:
>> What is a sensible number of ticks to take
>> into account for measurement?
> 
> Large enough that you get a stable average, but small enough that you
> can detect actual changes.

I figured out that much on my own :) I was just wondering if anybody had
already experimented with this...

> You can tell ALSA to timestamp all events that are received; just call
> the snd_seq_port_info_set_timestamping() function and set a queue that
> is running, then you'll get the queue's current time in each event.
> This isn't implemented in pyalsa, but you can set this for a specific
> connection with the queue, time_update, and time_real parameters of the
> connect_ports function.

I'll look into this.

Many thanks for your comments!

Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* pyalsa: SeqEvent.time strangeness (Was: synchronizing queue with MIDI clock events)
  2009-07-21 16:20   ` Christopher Arndt
@ 2009-07-31 18:26     ` Christopher Arndt
  2009-08-02 15:42       ` Christopher Arndt
  2009-08-03 11:55       ` Clemens Ladisch
  0 siblings, 2 replies; 13+ messages in thread
From: Christopher Arndt @ 2009-07-31 18:26 UTC (permalink / raw)
  To: alsa-devel

Christopher Arndt schrieb:
>> You can tell ALSA to timestamp all events that are received; just call
>> the snd_seq_port_info_set_timestamping() function and set a queue that
>> is running, then you'll get the queue's current time in each event.
>> This isn't implemented in pyalsa, but you can set this for a specific
>> connection with the queue, time_update, and time_real parameters of the
>> connect_ports function.

I've tested this now and encountered a very strange bevahior of the
event time set by the queue:

a) SeqEvent.time seems to be in milliseconds instead of seconds as would
be expected by the ALSA documentation and looking at the source of
pyalsa.alsaseq.

5) Consecutive timestamp go up to ~1000,00 and then seem to wrap around
and start from zereo again.

I have created a small test program, which demonstrates this:

http://paste.chrisarndt.de/paste/fa8ca7201bc7419f9e001315ca02b1ef

It outputs the time of each MIDI clock signal it receives and whether it
is in tick  or real time and whether it's absolute (= from the start of
the queue) or relative (to the preceding event). Here's some output from
the script:

MIDI CLOCK 0.0 ABS REAL
MIDI CLOCK 23.697488 ABS REAL
MIDI CLOCK 48.701538 ABS REAL
MIDI CLOCK 73.70515 ABS REAL
MIDI CLOCK 98.705762 ABS REAL
MIDI CLOCK 123.709812 ABS REAL
MIDI CLOCK 148.702424 ABS REAL
MIDI CLOCK 173.707474 ABS REAL
MIDI CLOCK 198.711086 ABS REAL
[...]
MIDI CLOCK 898.73904 ABS REAL
MIDI CLOCK 923.74909 ABS REAL
MIDI CLOCK 948.744702 ABS REAL
MIDI CLOCK 973.742314 ABS REAL
MIDI CLOCK 998.749364 ABS REAL
MIDI CLOCK 24.738976 ABS REAL
MIDI CLOCK 49.741026 ABS REAL
MIDI CLOCK 74.743638 ABS REAL
MIDI CLOCK 99.74725 ABS REAL

As you can see, once the time would exceed 1000.0 it seems to start from
zero again. This happens only when the queue sets the event times to
REAL. When ticks are used, the increase infinitely, as expected.

I fail to understand why this is and what I am doing wrong. I would
expect SeqEvent.time to be in seconds and always ascending until I stop
the queue. Please, somebody enlighten me!


Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: SeqEvent.time strangeness (Was: synchronizing queue with MIDI clock events)
  2009-07-31 18:26     ` pyalsa: SeqEvent.time strangeness (Was: synchronizing queue with MIDI clock events) Christopher Arndt
@ 2009-08-02 15:42       ` Christopher Arndt
  2009-08-03 11:55       ` Clemens Ladisch
  1 sibling, 0 replies; 13+ messages in thread
From: Christopher Arndt @ 2009-08-02 15:42 UTC (permalink / raw)
  To: alsa-devel

Christopher Arndt schrieb:
> I've tested this now and encountered a very strange bevahior of the
> event time set by the queue:
> [...]

Should I report this as a bug then? Is there a special category or
convention for filing pyalsa issues at https://bugtrack.alsa-project.org/ ?


Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: SeqEvent.time strangeness (Was: synchronizing queue with MIDI clock events)
  2009-07-31 18:26     ` pyalsa: SeqEvent.time strangeness (Was: synchronizing queue with MIDI clock events) Christopher Arndt
  2009-08-02 15:42       ` Christopher Arndt
@ 2009-08-03 11:55       ` Clemens Ladisch
  2009-08-03 12:21         ` pyalsa: SeqEvent.time strangeness Christopher Arndt
  1 sibling, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2009-08-03 11:55 UTC (permalink / raw)
  To: Christopher Arndt; +Cc: alsa-devel

Christopher Arndt wrote:
> I've tested this now and encountered a very strange bevahior of the
> event time set by the queue:
> 
> a) SeqEvent.time seems to be in milliseconds instead of seconds as would
> be expected by the ALSA documentation and looking at the source of
> pyalsa.alsaseq.
> 
> 5) Consecutive timestamp go up to ~1000,00 and then seem to wrap around
> and start from zereo again.

Apparently, you are the first one who tried to use this.  Fixed now:
http://git.alsa-project.org/?p=alsa-python.git;a=commitdiff;h=9a7dea33dddeb2d9d7693257323d43ccffbffed2


HTH
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: SeqEvent.time strangeness
  2009-08-03 11:55       ` Clemens Ladisch
@ 2009-08-03 12:21         ` Christopher Arndt
  2009-08-04  9:45           ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Christopher Arndt @ 2009-08-03 12:21 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 655 bytes --]

Clemens Ladisch schrieb:
> Christopher Arndt wrote:
>> I've tested this now and encountered a very strange bevahior of the
>> event time set by the queue:
> 
> Apparently, you are the first one who tried to use this.  Fixed now:
> http://git.alsa-project.org/?p=alsa-python.git;a=commitdiff;h=9a7dea33dddeb2d9d7693257323d43ccffbffed2

Excelllent! The test script now produces correct results.
Thanks for the fix!

Might I suggest another patch to pyalsa? This would allow to use
developers to use "python setup.py develop" to install their git version
as a Python egg-link and makes it much easier to use pyalasa with
virtual Python environments.


Chris

[-- Attachment #2: setuptools.diff --]
[-- Type: text/plain, Size: 323 bytes --]

diff --git a/setup.py b/setup.py
index fa7f2d6..c2b6389 100755
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,10 @@
 
 import os
 import sys
-from distutils.core import setup, Extension
+try:
+    from setuptools import setup, Extension
+except ImportError:
+    from distutils.core import setup, Extension
 
 VERSION='1.0.20'
 

[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: pyalsa: SeqEvent.time strangeness
  2009-08-03 12:21         ` pyalsa: SeqEvent.time strangeness Christopher Arndt
@ 2009-08-04  9:45           ` Clemens Ladisch
  2009-08-04 11:10             ` Christopher Arndt
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2009-08-04  9:45 UTC (permalink / raw)
  To: Christopher Arndt; +Cc: alsa-devel

Christopher Arndt wrote:
> Might I suggest another patch to pyalsa?

Please provide a Signed-off-by line.


Best regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: SeqEvent.time strangeness
  2009-08-04  9:45           ` Clemens Ladisch
@ 2009-08-04 11:10             ` Christopher Arndt
  2009-08-04 13:03               ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Christopher Arndt @ 2009-08-04 11:10 UTC (permalink / raw)
  To: alsa-devel

Clemens Ladisch schrieb:
> Christopher Arndt wrote:
>> Might I suggest another patch to pyalsa?
> 
> Please provide a Signed-off-by line.

Please forgive my ignorance, but what is that? I'm unfamiliar with the
alsa development process. Is that a git-specific thing? Is there some
documentation on contributing to alsa?


Chris

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: pyalsa: SeqEvent.time strangeness
  2009-08-04 11:10             ` Christopher Arndt
@ 2009-08-04 13:03               ` Clemens Ladisch
  2009-08-05 13:18                 ` [PATCH] alsa-python: Add support for setuptools Christopher Arndt
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2009-08-04 13:03 UTC (permalink / raw)
  To: alsa-devel

Christopher Arndt wrote:
> Clemens Ladisch schrieb:
> > Please provide a Signed-off-by line.
> 
> Please forgive my ignorance, but what is that? I'm unfamiliar with the
> alsa development process.

It's originally a Linux kernel development process thing, but we use it
for all of ALSA.  See section 12 of
<http://git.alsa-project.org/?p=alsa-kernel.git;a=blob;f=Documentation/SubmittingPatches;hb=HEAD>.


HTH
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH] alsa-python: Add support for setuptools
  2009-08-04 13:03               ` Clemens Ladisch
@ 2009-08-05 13:18                 ` Christopher Arndt
  2009-08-05 13:30                   ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Christopher Arndt @ 2009-08-05 13:18 UTC (permalink / raw)
  To: alsa-devel

This patch adds support for setuptools to the setup.py file of python-alsa.

Signed-off-by: Christopher Arndt <chris@chrisarndt.de>

diff --git a/setup.py b/setup.py
index fa7f2d6..c2b6389 100755
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,10 @@

 import os
 import sys
-from distutils.core import setup, Extension
+try:
+    from setuptools import setup, Extension
+except ImportError:
+    from distutils.core import setup, Extension

 VERSION='1.0.20'

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH] alsa-python: Add support for setuptools
  2009-08-05 13:18                 ` [PATCH] alsa-python: Add support for setuptools Christopher Arndt
@ 2009-08-05 13:30                   ` Clemens Ladisch
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Ladisch @ 2009-08-05 13:30 UTC (permalink / raw)
  To: Christopher Arndt; +Cc: alsa-devel

Christopher Arndt wrote:
> This patch adds support for setuptools to the setup.py file of python-alsa.

Applied now.  Thanks!


Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-08-05 13:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-17 12:54 pyalsa: synchronizing queue with MIDI clock events Christopher Arndt
2009-07-20 12:31 ` Christopher Arndt
2009-07-21 13:32 ` Clemens Ladisch
2009-07-21 16:20   ` Christopher Arndt
2009-07-31 18:26     ` pyalsa: SeqEvent.time strangeness (Was: synchronizing queue with MIDI clock events) Christopher Arndt
2009-08-02 15:42       ` Christopher Arndt
2009-08-03 11:55       ` Clemens Ladisch
2009-08-03 12:21         ` pyalsa: SeqEvent.time strangeness Christopher Arndt
2009-08-04  9:45           ` Clemens Ladisch
2009-08-04 11:10             ` Christopher Arndt
2009-08-04 13:03               ` Clemens Ladisch
2009-08-05 13:18                 ` [PATCH] alsa-python: Add support for setuptools Christopher Arndt
2009-08-05 13:30                   ` Clemens Ladisch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.