All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: How to tell how many frames gone to PCM
  2005-04-26 20:18 How to tell how many frames gone to PCM Steve deRosier
@ 2005-04-26 20:16 ` Lee Revell
  2005-04-26 21:07   ` Steve deRosier
       [not found] ` <ad2655cb0504270201165f9859@mail.gmail.com>
  1 sibling, 1 reply; 13+ messages in thread
From: Lee Revell @ 2005-04-26 20:16 UTC (permalink / raw)
  To: Steve deRosier; +Cc: Alsa-Devel

On Tue, 2005-04-26 at 13:18 -0700, Steve deRosier wrote:
> All,
> 
> I'm having issues w/ synchronizing MIDI and audio data I output via Alsa.  I'm working through my program trying to confirm data flow and I need some help.
> 
> Is there a particular function (or other method) I can use to tell me the number of frames I have sent to alsa via snd_pcm_writei()?  

Just keep track of it yourself.  snd_pcm_writei() returns the number of
frames written on each call, so keep a running total.

Lee



-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* How to tell how many frames gone to PCM
@ 2005-04-26 20:18 Steve deRosier
  2005-04-26 20:16 ` Lee Revell
       [not found] ` <ad2655cb0504270201165f9859@mail.gmail.com>
  0 siblings, 2 replies; 13+ messages in thread
From: Steve deRosier @ 2005-04-26 20:18 UTC (permalink / raw)
  To: Alsa-Devel

All,

I'm having issues w/ synchronizing MIDI and audio data I output via Alsa.  I'm working through my program trying to confirm data flow and I need some help.

Is there a particular function (or other method) I can use to tell me the number of frames I have sent to alsa via snd_pcm_writei()?  

Either type would be good:
---
open pcm
write all data
get # frames written
close pcm
--- or
open pcm
get current frame count
write all data
get new frame count
print new - old counts
close pcm
---

Any help you could give would be appreciated.

Thanks,
- Steve


-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-26 20:16 ` Lee Revell
@ 2005-04-26 21:07   ` Steve deRosier
  2005-04-26 21:17     ` Lee Revell
  0 siblings, 1 reply; 13+ messages in thread
From: Steve deRosier @ 2005-04-26 21:07 UTC (permalink / raw)
  To: Lee Revell; +Cc: Alsa-Devel

Yeah, already doing that.  I was hoping there was something else I could use to confirm the numbers I'm getting.

Here's the problem...

In order to get my MIDI and audio to sync up, I found about 1.5 years ago I had to add +4 to my sample count per PERIOD_SIZE number of samples I sent to the PCM.  I calculate my midi out time via the number of samples I've sent to the PCM.  I never could account for the discrepancy, and eventually settled for the hack (with a big fat comment in the code and a bug note in our bugzilla) in order to get our first software version shipped.  As you might imagine, this has come back to haunt me periodically as we continue to maintain the software.  It could be I NEED to do what I do in the hack do to something I'm not realizing, but it bothers me when I've got to do something I don't understand and is not supported by the assumptions in the system.  It could be something I'm doing weird (say an off by one bug in the code), or that I'm not using alsa right, but I've not been able to find it.

Now I'm against the wall and I've got to solve the problem (or at least understand why I have to do what I'm doing).  

Using the return value seems to report the expected number of frames as what I sent.  Frankly I was hoping that I'm not sending the expected number of frames to the PCM, figuring that it would give me a string to pull on.

Any more ideas would be great.

Thanks,
- Steve

Lee Revell wrote:
> On Tue, 2005-04-26 at 13:18 -0700, Steve deRosier wrote:
> 
>> All,
>> 
>> I'm having issues w/ synchronizing MIDI and audio data I output via
>> Alsa.  I'm working through my program trying to confirm data flow
>> and I need some help.
>> 
>> Is there a particular function (or other method) I can use to tell
>> me the number of frames I have sent to alsa via snd_pcm_writei()?
>> 
> 
> 
> Just keep track of it yourself.  snd_pcm_writei() returns the number
> of frames written on each call, so keep a running total.
> 
> Lee
> 


-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-26 21:07   ` Steve deRosier
@ 2005-04-26 21:17     ` Lee Revell
  2005-04-26 21:45       ` Steve deRosier
  0 siblings, 1 reply; 13+ messages in thread
From: Lee Revell @ 2005-04-26 21:17 UTC (permalink / raw)
  To: Steve deRosier; +Cc: Alsa-Devel

On Tue, 2005-04-26 at 14:07 -0700, Steve deRosier wrote:
> Any more ideas would be great.
> 

One possibility is that you are hitting an ALSA bug.  Some fixes have
been merged since ALSA 1.0.8 for bugs that could account for the strange
behavior.  The first thing to do is verify the problem does not appear
with a newer ALSA.

Another idea, by default the MIDI timing will be driven by the system
timer, while the PCM will be driven by the soundcard timer, even if your
MIDI port is on the same board as your audio.  Although I would expect
the drift to be very small.

As a last resort, you could hack the low level driver to keep track of
the frames written to the hardware.  Add a counter to the chip structure
and increment it in the interrupt handler.

Lee



-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-26 21:17     ` Lee Revell
@ 2005-04-26 21:45       ` Steve deRosier
  2005-04-27 14:36         ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Steve deRosier @ 2005-04-26 21:45 UTC (permalink / raw)
  To: Lee Revell; +Cc: Alsa-Devel

> 
> One possibility is that you are hitting an ALSA bug.  Some fixes have
> been merged since ALSA 1.0.8 for bugs that could account for the strange
> behavior.  The first thing to do is verify the problem does not appear
> with a newer ALSA.
> 

I'll have to try that.  I think we're running 1.0.4 at the moment.  We hesitate to update at this point due to most things just working (mine is the only alsa using program in the system experiencing this problem) and we have a headache every time we upgrade, but maybe it won't be so hard this time around since the API has solidified more than in earlier upgrade tries.

> Another idea, by default the MIDI timing will be driven by the system
> timer, while the PCM will be driven by the soundcard timer, even if your
> MIDI port is on the same board as your audio.  Although I would expect
> the drift to be very small.
> 
I should (if I did it right) have the pcm and midi timers linked.  I use two different classes for output, one for the PCM (called CDSP) and one for the MIDI (called CMIDIPort).  Usually this makes things simple, but linking the clocks requires pasing info back and forth between the two.  My thread does this:
---
mPCMInfo = mDSP.GetInfo();
if( !mPCMInfo )
  return false;
  
if( !mMIDIPort.LinkPCMTimer( mPCMInfo ) )
  return false;

return true;  
---

calling CDSP::GetInfo():
---
snd_pcm_info_t * CDSP::GetInfo( void )
{
  snd_pcm_info_t * PCMInfo;
  
  snd_pcm_info_malloc( &PCMInfo );
  int err = snd_pcm_info( hPCM, PCMInfo );
  if( err < 0 )
  {
    FreeInfo( PCMInfo );
    return NULL;
  }
    
  return PCMInfo;  
}
---

And to actually link the timers:
---
bool CMIDIPort::LinkPCMTimer( const snd_pcm_info_t * PCMInfo )
{
  if( !PCMInfo )
    return false;
    
  snd_seq_queue_timer_t * QueueTimer;
  snd_timer_id_t * QTID;
    
  // get the info we need
  int Card = snd_pcm_info_get_card( PCMInfo );
  unsigned int Device = snd_pcm_info_get_device( PCMInfo );
  unsigned int SDevice = snd_pcm_info_get_subdevice( PCMInfo );
  SDevice = SDevice << 1;
  // check for bad return
  if( ( Card < 0 ) ) 
    return false;
    
  // build our timers
  snd_seq_queue_timer_alloca( &QueueTimer );
  snd_timer_id_alloca( &QTID );
  
  if( snd_seq_get_queue_timer( hSeq, mQueue, QueueTimer ) < 0 )
    return false;
  
  // setup the data that links us to the PCM
  snd_timer_id_set_class( QTID, SND_TIMER_CLASS_PCM );
  snd_timer_id_set_sclass( QTID, SND_TIMER_SCLASS_NONE );
  snd_timer_id_set_card( QTID, Card );
  snd_timer_id_set_device( QTID, Device );
  snd_timer_id_set_subdevice( QTID, SDevice );


  // setup the actual timer
  snd_seq_queue_timer_set_type( QueueTimer, SND_SEQ_TIMER_ALSA );
  snd_seq_queue_timer_set_id( QueueTimer, QTID );
  snd_seq_set_queue_timer( hSeq, mQueue, QueueTimer );
  
  return true;
}
---

Is that done right?  Is there something I'm forgetting to do?



> As a last resort, you could hack the low level driver to keep track of
> the frames written to the hardware.  Add a counter to the chip structure
> and increment it in the interrupt handler.
> 
Ick.  Last resort definately.  Though I have hacked some of the drivers before, I'd just rather not; you know what I mean?  ;)  

Thanks,
- Steve



-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-26 21:45       ` Steve deRosier
@ 2005-04-27 14:36         ` Clemens Ladisch
  2005-04-27 16:56           ` Steve deRosier
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2005-04-27 14:36 UTC (permalink / raw)
  To: Steve deRosier; +Cc: Lee Revell, Alsa-Devel

Steve deRosier wrote:
> > Another idea, by default the MIDI timing will be driven by the system
> > timer, while the PCM will be driven by the soundcard timer, even if your
> > MIDI port is on the same board as your audio.  Although I would expect
> > the drift to be very small.

Oh, you really expect the (potentially overclocked) system clock and
the cheapo sound card crystal to be accurate?  ;-)

> I should (if I did it right) have the pcm and midi timers linked.
>
>   // setup the data that links us to the PCM
>   snd_timer_id_set_class( QTID, SND_TIMER_CLASS_PCM );
>   snd_timer_id_set_sclass( QTID, SND_TIMER_SCLASS_NONE );
>   snd_timer_id_set_card( QTID, Card );
>   snd_timer_id_set_device( QTID, Device );
>   snd_timer_id_set_subdevice( QTID, SDevice );
>
>   // setup the actual timer
>   snd_seq_queue_timer_set_type( QueueTimer, SND_SEQ_TIMER_ALSA );
>   snd_seq_queue_timer_set_id( QueueTimer, QTID );
>   snd_seq_set_queue_timer( hSeq, mQueue, QueueTimer );
>
> Is that done right?  Is there something I'm forgetting to do?

You should check the error code, but otherwise this looks OK.

Are the inaccuracies you're seeing consistent, and/or dependent on
some specific hardware?


Regards,
Clemens



-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
       [not found] ` <ad2655cb0504270201165f9859@mail.gmail.com>
@ 2005-04-27 16:43   ` Steve deRosier
  0 siblings, 0 replies; 13+ messages in thread
From: Steve deRosier @ 2005-04-27 16:43 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: Alsa-Devel

> 
> You might want the "snd_pcm_delay()" function.
> This will return a count of frames in the buffer that have not yet
> reached the ADC.
> E.g.
> snd_pcm_write()   <- Write 1024 frames to the buffer.
> snd_pcm_delay()  <- If this returns 500, it means that 525 frames have
> already been played out of the speakers.
> 
> The snd_pcm_delay() function was introduced into alsa to help
> audio/video application do lip sync. We could therefore calculate that
> if we write a frame to the buffer now, it will reach the speakers in
> exactly snd_pcm_delay() frames time.
> 
> Does this help you?

I've got it implemented in my system, but actually it doesn't solve the problem (and actually exasperates it).

See, we calculate the midi times based on the "sample" time that the midi msg arrives at.

So, for example:

Our AlsaSender task receives a right and left audio sample (the two together I suppose is called a frame), and the last MIDI byte of a message.  It keeps a counter of how many audio frames are received at this point.  It sends the audio frame to alsa (actually the CDSP function buffers up PERIOD_SIZE number of samples before it does the ..._writei() in order to not cause excessive function call overhead).  It calculates the MIDI timestamp based on the number of samples it has sent off:

snd_seq_real_time_t time;
unsigned long long int iTime = (((mPlayedSampleCount*10*P_MILLION)/441);
time.tv_sec = iTime/P_BILLION;
time.tv_nsec = iTime%P_BILLION;

snd_seq_ev_set_source(&event, mPort);
snd_seq_ev_set_subs(&event);
snd_seq_ev_schedule_real(&event, mQueue, 0, &time);
snd_seq_event_output(hSeq, &event);
snd_seq_drain_output(hSeq);

Our audio source is CD, so 44100 is the correct speed for the calculation (non-significant zeros canceled off in the calculation).

Anything obviously wrong with my approach?

Thanks,
- Steve


-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-27 14:36         ` Clemens Ladisch
@ 2005-04-27 16:56           ` Steve deRosier
  2005-04-27 17:22             ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Steve deRosier @ 2005-04-27 16:56 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Lee Revell, Alsa-Devel

Clemens Ladisch wrote:
> Steve deRosier wrote:
> 
>>>Another idea, by default the MIDI timing will be driven by the system
>>>timer, while the PCM will be driven by the soundcard timer, even if your
>>>MIDI port is on the same board as your audio.  Although I would expect
>>>the drift to be very small.
> 
> 
> Oh, you really expect the (potentially overclocked) system clock and
> the cheapo sound card crystal to be accurate?  ;-)
> 
Nope.  Though, in our case not overclocked but with other issues, see below...

> 
>>I should (if I did it right) have the pcm and midi timers linked.
>>
>>  // setup the data that links us to the PCM
>>  snd_timer_id_set_class( QTID, SND_TIMER_CLASS_PCM );
>>  snd_timer_id_set_sclass( QTID, SND_TIMER_SCLASS_NONE );
>>  snd_timer_id_set_card( QTID, Card );
>>  snd_timer_id_set_device( QTID, Device );
>>  snd_timer_id_set_subdevice( QTID, SDevice );
>>
>>  // setup the actual timer
>>  snd_seq_queue_timer_set_type( QueueTimer, SND_SEQ_TIMER_ALSA );
>>  snd_seq_queue_timer_set_id( QueueTimer, QTID );
>>  snd_seq_set_queue_timer( hSeq, mQueue, QueueTimer );
>>
>>Is that done right?  Is there something I'm forgetting to do?
> 
> 
> You should check the error code, but otherwise this looks OK.
> 
Error code for which function?  It's been a long time since I wrote the code and frankly I'm not 100% sure I understand it anyway.

> Are the inaccuracies you're seeing consistent, and/or dependent on
> some specific hardware?
Doubtful.  And not dependent uppon a particular Alsa version either (though I'm in the process of upgrading my Alsa to 1.0.9rc2 in order to get current and eliminate that concern).  See, we've got another player on the system (let's call it a "file player") that plays in sync just fine, but my program ("CD player" if you will) won't.  Now, since mine came second, much of the Alsa functionality was modeled off the "file player" so they are very similar in Alsa specifics (though hugely different in structure, purpose, and archetecture).

Here's a question... I'd like to get the current time from both the PCM and the MIDI device in order to confirm they've got the clock linked. Is there a meaningful way to test that?

Thanks,
- Steve




-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-27 16:56           ` Steve deRosier
@ 2005-04-27 17:22             ` Clemens Ladisch
  2005-04-27 20:31               ` Steve deRosier
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2005-04-27 17:22 UTC (permalink / raw)
  To: Steve deRosier; +Cc: Alsa-Devel

Steve deRosier wrote:
> Clemens Ladisch wrote:
> > You should check the error code, but otherwise this looks OK.
>
> Error code for which function?

snd_seq_set_queue_timer (it's the only nontrivial function, the others
just set parameters for this one)

As a rule, every error code should be checked.

> Here's a question... I'd like to get the current time from both
> the PCM and the MIDI device in order to confirm they've got the
> clock linked. Is there a meaningful way to test that?

There is no PCM time per se, you have to use the frame count as time.

A MIDI queue doesn't have its own "real time" either; whenever you use
a "real time" timestamp you end up using the system clock.  Only the
tick counter is synchronized to the timer interrupt.  (And no, this
isn't documented anywhere.)

And I guess this is your problem -- it should go away if you schedule
the MIDI events using ticks instead of real time.

The nice thing about using ticks is that you can set them up to be any
quantity you want (in this case probably the same as one PCM frame or
period).


HTH
Clemens



-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-27 17:22             ` Clemens Ladisch
@ 2005-04-27 20:31               ` Steve deRosier
  2005-04-28  8:25                 ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Steve deRosier @ 2005-04-27 20:31 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Alsa-Devel



Clemens Ladisch wrote:
> Steve deRosier wrote:
> 
>>Clemens Ladisch wrote:
>>
>>>You should check the error code, but otherwise this looks OK.
>>
>>Error code for which function?
> 
> 
> snd_seq_set_queue_timer (it's the only nontrivial function, the others
> just set parameters for this one)
> 
> As a rule, every error code should be checked.

Agreed.  Must have missed that one; fixed, thanks.

>>Here's a question... I'd like to get the current time from both
>>the PCM and the MIDI device in order to confirm they've got the
>>clock linked. Is there a meaningful way to test that?
> 
> 
> There is no PCM time per se, you have to use the frame count as time.
> 
> A MIDI queue doesn't have its own "real time" either; whenever you use
> a "real time" timestamp you end up using the system clock.  Only the
> tick counter is synchronized to the timer interrupt.  (And no, this
> isn't documented anywhere.)
> 
> And I guess this is your problem -- it should go away if you schedule
> the MIDI events using ticks instead of real time.
> 
> The nice thing about using ticks is that you can set them up to be any
> quantity you want (in this case probably the same as one PCM frame or
> period).
> 

Interesting!  Thats a real clue for once.  Looking back over our other Alsa players, I'm noticing they're all using ticks, not real time scheduling.  Forgeting the +4/PERIOD_SIZE hack I've got in there for a moment (I must have a culmative off-by-one error somewhere), this player always seemed sloppy, where as the other player was real crisp.  Would I be guessing right that if several real-time scheduled events were supposed to go out, but built up till the tick happened, all of those would be sent out and then more events would buffer till the next tick?  

Ok, I'm changing to tick-based timing.  How do I setup my tick timing?  Is the sample code in the docs what I'm looking for?:
void set_tempo(snd_seq_t *handle)
{
        snd_seq_queue_tempo_t *tempo;
        snd_seq_queue_tempo_alloca(&tempo);
        snd_seq_queue_tempo_set_tempo(tempo, 1000000); // 60 BPM
        snd_seq_queue_tempo_set_ppq(tempo, 48); // 48 PPQ
        snd_seq_set_queue_tempo(handle, tempo);
}

Ideas of the PPQ and BPM I should use to match 1 tick to 1 frame?

Thanks,
- Steve


-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-27 20:31               ` Steve deRosier
@ 2005-04-28  8:25                 ` Clemens Ladisch
  2005-05-02 18:04                   ` Steve deRosier
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2005-04-28  8:25 UTC (permalink / raw)
  To: Steve deRosier; +Cc: Alsa-Devel

Steve deRosier wrote:
> Forgeting the +4/PERIOD_SIZE hack I've got in there for a moment
> (I must have a culmative off-by-one error somewhere),

No, the events are usiong the wrong clock.  Real-time scheduling uses
the system clock instead of the timer source you've set for the queue.
That is, at every timer interrupt, ALSA checks whether the system time
has reached the scheduled event time.  OTOH, MIDI ticks are calculated
using the timer interrupt frequency.

> this player always seemed sloppy, where as the other player was
> real crisp.  Would I be guessing right that if several real-time
> scheduled events were supposed to go out, but built up till the
> tick happened, all of those would be sent out and then more events
> would buffer till the next tick?

Yes.  Events are sent out at every timer interrupt.  This is true for
both real-time and tick scheduled events

> Clemens Ladisch wrote:
> > The nice thing about using ticks is that you can set them up to be any
> > quantity you want (in this case probably the same as one PCM frame or
> > period).
>
> Ok, I'm changing to tick-based timing.  How do I setup my tick
> timing?  Is the sample code in the docs what I'm looking for?:

Yes.

> Ideas of the PPQ and BPM I should use to match 1 tick to 1 frame?

I'd use one quarter note per second (tempo = 1000000 microseconds per
quarter note) so that the sampling frequency can be used directly as
PPQ (ticks per quarter note).


HTH
Clemens



-------------------------------------------------------
SF.Net email is sponsored by: Tell us your software development plans!
Take this survey and enter to win a one-year sub to SourceForge.net
Plus IDC's 2005 look-ahead and a copy of this survey
Click here to start!  http://www.idcswdc.com/cgi-bin/survey?id=105hix

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

* Re: How to tell how many frames gone to PCM
  2005-04-28  8:25                 ` Clemens Ladisch
@ 2005-05-02 18:04                   ` Steve deRosier
  2005-05-03  8:05                     ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Steve deRosier @ 2005-05-02 18:04 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Alsa-Devel

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

Clemens Ladisch wrote:
> Steve deRosier wrote:
> 
>>Forgeting the +4/PERIOD_SIZE hack I've got in there for a moment
>>(I must have a culmative off-by-one error somewhere),
> 
> 
> No, the events are usiong the wrong clock.  Real-time scheduling uses
> the system clock instead of the timer source you've set for the queue.
> That is, at every timer interrupt, ALSA checks whether the system time
> has reached the scheduled event time.  OTOH, MIDI ticks are calculated
> using the timer interrupt frequency.
> 

So, even though I tied the MIDI timer source to the pcm timer, if I use real-time events, those events will use the system clock?  I figured the MIDI timer would just be used and the time just calculated via whatever the MIDI timer was doing.

> 
>>Ideas of the PPQ and BPM I should use to match 1 tick to 1 frame?
> 
> 
> I'd use one quarter note per second (tempo = 1000000 microseconds per
> quarter note) so that the sampling frequency can be used directly as
> PPQ (ticks per quarter note).

While waiting for your answer, I decided to keep the tempo the "same" as what I was using, tempo = 500000 so that tempo changes wouldn't need to adjuct the PPQ, so came up with a PPQ = 22050.  This should be equivelent as tempo = 1000000; PPQ = 44100 (which I tried with the same results).  All is fine in my calculation as near as I can tell (PCM data is standard CD of 44100 samples/sec).

BUT...

The MIDI plays WAY too slow.  I don't get it.  I can speed it up clearly by using a larger PPQ or smaller tempo, but I can't seem to do it in any manner that will get my MIDI to line up with my audio.

I notice in /proc/asound/card0/pcm0p/sub0/hw_params gives a tick_time of 1000.  Would that affect anything since I'm triggering the queue time off the pcm?

Including lots of proc data incase there's a clue there I don't know about.

Thanks,
- Steve

[-- Attachment #2: opus_alsa.txt --]
[-- Type: text/plain, Size: 8035 bytes --]

# cat pcm
00-00: VIA 82C686A/B rev50 : VIA 82C686A/B rev50 : playback 1 : capture 1
# cd card0
# ls
codec97#0  id         midi0      pcm0c      pcm0p      via82xx
# cd pcm0p
# ls
info  sub0
# cat info
card: 0
device: 0
subdevice: 0
stream: PLAYBACK
id: VIA 82C686A/B rev50
name: VIA 82C686A/B rev50
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 0
# cd sub0
# ls
hw_params  info       prealloc   status     sw_params
# cat info
card: 0
device: 0
subdevice: 0
stream: PLAYBACK
id: VIA 82C686A/B rev50
name: VIA 82C686A/B rev50
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 0
# cat hw_params
access: RW_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 2048
buffer_size: 16384
tick_time: 1000
# cat prealloc
64
# cat status
state: RUNNING
trigger_time: 1115052640.065836000
tstamp      : 1115052699.379423000
delay       : 15388
avail       : 996
avail_max   : 8562
-----
hw_ptr      : 2616292
appl_ptr    : 2631680
# cat sw_params
tstamp_mode: NONE
period_step: 1
sleep_min: 0
avail_min: 2048
xfer_align: 1
start_threshold: 8192
stop_threshold: 32768
silence_threshold: 0
silence_size: 0
boundary: 1073741824
# cd ..
# cd ..
# ls
codec97#0  id         midi0      pcm0c      pcm0p      via82xx
# cd ..
# ls
Opus7    card0    card1    cards    devices  pcm      rev50    seq      timers   version
# cd card1
# ls
id     midi0
# cat id
Opus7
# cat midi0
uart16550 MIDI #0

Output 0
  Tx bytes     : 130751
  Mode         : native
  Buffer size  : 4096
  Avail        : 4096
Output 1
  Tx bytes     : 0
Output 2
  Tx bytes     : 37961
  Mode         : native
  Buffer size  : 4096
  Avail        : 4096
Input 0
  Rx bytes     : 2688
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
Input 1
  Rx bytes     : 0
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
Input 2
  Rx bytes     : 1751
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
# cat midi0
uart16550 MIDI #0

Output 0
  Tx bytes     : 130795
  Mode         : native
  Buffer size  : 4096
  Avail        : 4096
Output 1
  Tx bytes     : 0
Output 2
  Tx bytes     : 37961
  Mode         : native
  Buffer size  : 4096
  Avail        : 4096
Input 0
  Rx bytes     : 2688
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
Input 1
  Rx bytes     : 0
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
Input 2
  Rx bytes     : 1751
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
# cat midi0
uart16550 MIDI #0

Output 0
  Tx bytes     : 131098
  Mode         : native
  Buffer size  : 4096
  Avail        : 4096
Output 1
  Tx bytes     : 0
Output 2
  Tx bytes     : 37961
  Mode         : native
  Buffer size  : 4096
  Avail        : 4096
Input 0
  Rx bytes     : 2688
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
Input 1
  Rx bytes     : 0
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
Input 2
  Rx bytes     : 1751
  Buffer size  : 4096
  Avail        : 0
  Overruns     : 0
# ls
id     midi0
# cd ..
# ls
Opus7    card0    card1    cards    devices  pcm      rev50    seq      timers   version
# ls -l
lrwxrwxrwx    1 root     root            5 May  2 09:53 Opus7 -> card1
dr-xr-xr-x    5 root     root            0 May  2 09:53 card0
dr-xr-xr-x    2 root     root            0 May  2 09:53 card1
-r--r--r--    1 root     root            0 May  2 09:53 cards
-r--r--r--    1 root     root            0 May  2 09:53 devices
-r--r--r--    1 root     root            0 May  2 09:53 pcm
lrwxrwxrwx    1 root     root            5 May  2 09:53 rev50 -> card0
dr-xr-xr-x    2 root     root            0 May  2 09:53 seq
-r--r--r--    1 root     root            0 May  2 09:53 timers
-r--r--r--    1 root     root            0 May  2 09:53 version
# cd seq
# ls
clients  drivers  queues   timer
# cat timer
Timer for queue 0 : RTC timer
  Period time : 0.000976562
  Skew : 65536 / 65536
Timer for queue 1 : RTC timer
  Period time : 0.000976562
  Skew : 65536 / 65536
Timer for queue 2 : RTC timer
  Period time : 0.000976562
  Skew : 65536 / 65536
Timer for queue 3 : RTC timer
  Period time : 0.000976562
  Skew : 65536 / 65536
Timer for queue 4 : PCM playback 0-0-0
  Period time : 0.046545454
  Skew : 65536 / 65536
# cat queues
queue 0: [Queue-0]
owned by client    : 128
lock status        : Locked
queued time events : 0
queued tick events : 0
timer state        : Running
timer PPQ          : 480
current tempo      : 500000
current BPM        : 120
current time       : 319196.794578970 s
current tick       : 306429118

queue 1: [Queue-1]
owned by client    : 129
lock status        : Locked
queued time events : 0
queued tick events : 0
timer state        : Running
timer PPQ          : 480
current tempo      : 500000
current BPM        : 120
current time       : 319196.793602408 s
current tick       : 306429117

queue 2: [Queue-2]
owned by client    : 130
lock status        : Locked
queued time events : 0
queued tick events : 0
timer state        : Running
timer PPQ          : 480
current tempo      : 500000
current BPM        : 120
current time       : 319196.793602408 s
current tick       : 306429117

queue 3: [Queue-3]
owned by client    : 131
lock status        : Locked
queued time events : 0
queued tick events : 0
timer state        : Running
timer PPQ          : 480
current tempo      : 500000
current BPM        : 120
current time       : 319196.792625846 s
current tick       : 306429117

queue 4: [Queue-4]
owned by client    : 132
lock status        : Locked
queued time events : 0
queued tick events : 14
timer state        : Running
timer PPQ          : 44100
current tempo      : 1000000
current BPM        : 60
current time       : 2.141090884 s
current tick       : 94425

# ls
clients  drivers  queues   timer
# cat drivers
snd-seq-midi,loaded,2
# cat clients
Client info
  cur  clients : 9
  peak clients : 12
  max  clients : 192

Client   0 : "System" [Kernel]
  Port   0 : "Timer" (Rwe-)
  Port   1 : "Announce" (R-e-)
Client  62 : "Midi Through" [Kernel]
  Port   0 : "Midi Through Port-0" (RWe-)
Client  64 : "VIA 82C686A/B rev50 MIDI - Rawmidi 0" [Kernel]
  Port   0 : "VIA 82C686A/B rev50 MIDI" (RWeX)
Client  72 : "uart16550 MIDI #0 - Rawmidi 1" [Kernel]
  Port   0 : "uart16550 MIDI #0-0" (RWeX)
    Connecting To: 129:0[t:1]
    Connected From: 131:0
  Port   1 : "uart16550 MIDI #0-1" (RWeX)
    Connecting To: 128:0[r:0]
  Port   2 : "uart16550 MIDI #0-2" (RWeX)
    Connecting To: 129:0
    Connected From: 130:0
Client 128 : "Client-128" [User]
  Port   0 : "In" (-We-)
    Connected From: 72:1[r:0], 132:0
  Output pool :
    Pool size          : 500
    Cells in use       : 0
    Peak cells in use  : 0
    Alloc success      : 0
    Alloc failures     : 0
  Input pool :
    Pool size          : 200
    Cells in use       : 0
    Peak cells in use  : 4
    Alloc success      : 1380
    Alloc failures     : 0
Client 129 : "Client-129" [User]
  Port   0 : "In" (-We-)
    Connected From: 72:0[t:1], 72:2
  Output pool :
    Pool size          : 500
    Cells in use       : 0
    Peak cells in use  : 0
    Alloc success      : 0
    Alloc failures     : 0
  Input pool :
    Pool size          : 200
    Cells in use       : 0
    Peak cells in use  : 2
    Alloc success      : 23
    Alloc failures     : 0
Client 130 : "Client-130" [User]
  Port   0 : "Out" (R-e-)
    Connecting To: 72:2
  Output pool :
    Pool size          : 500
    Cells in use       : 0
    Peak cells in use  : 32
    Alloc success      : 64
    Alloc failures     : 0
Client 131 : "Client-131" [User]
  Port   0 : "Out" (R-e-)
    Connecting To: 72:0
  Output pool :
    Pool size          : 500
    Cells in use       : 0
    Peak cells in use  : 4
    Alloc success      : 1373
    Alloc failures     : 0
Client 132 : "Client-132" [User]
  Port   0 : "Out" (R-e-)
    Connecting To: 128:0
  Output pool :
    Pool size          : 500
    Cells in use       : 66
    Peak cells in use  : 66
    Alloc success      : 128
    Alloc failures     : 0

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

* Re: How to tell how many frames gone to PCM
  2005-05-02 18:04                   ` Steve deRosier
@ 2005-05-03  8:05                     ` Clemens Ladisch
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Ladisch @ 2005-05-03  8:05 UTC (permalink / raw)
  To: Steve deRosier; +Cc: Alsa-Devel

Steve deRosier wrote:
> So, even though I tied the MIDI timer source to the pcm timer, if
> I use real-time events, those events will use the system clock?
> I figured the MIDI timer would just be used and the time just
> calculated via whatever the MIDI timer was doing.

Only the 'tick' time is calculated based on timer ticks.  The 'real'
time uses the system clock.

> I notice in /proc/asound/card0/pcm0p/sub0/hw_params gives a
> tick_time of 1000.  Would that affect anything since I'm
> triggering the queue time off the pcm?

No, this is not related to the PCM timer.  Interrupts happen at every
period boundary ...

> # cat hw_params
> rate: 44100 (44100/1)
> period_size: 2048

... at about 21.5 Hz (44100/2048).

You might want to use smaller periods to reduce the MIDI jitter.

> The MIDI plays WAY too slow.  I don't get it.  I can speed it up
> clearly by using a larger PPQ or smaller tempo, but I can't seem
> to do it in any manner that will get my MIDI to line up with my
> audio.
>
> queue 4: [Queue-4]
> timer PPQ          : 44100
> current tempo      : 1000000
> current BPM        : 60
> current time       : 2.141090884 s
> current tick       : 94425

If we assume that the system clock and the PCM clocks are almost in
sync, the theoretical tick time should be 2.141090884 * 44100 = 94422.
The value above looks OK.

There will be some (more or less constant) delay between the MIDI
events and the corresponding PCM samples, depending of the delays in
both devices, but I cannot see how MIDI events could have the wrong
tempo.


Regards,
Clemens



-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.
Get your fingers limbered up and give it your best shot. 4 great events, 4
opportunities to win big! Highest score wins.NEC IT Guy Games. Play to
win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20

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

end of thread, other threads:[~2005-05-03  8:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-26 20:18 How to tell how many frames gone to PCM Steve deRosier
2005-04-26 20:16 ` Lee Revell
2005-04-26 21:07   ` Steve deRosier
2005-04-26 21:17     ` Lee Revell
2005-04-26 21:45       ` Steve deRosier
2005-04-27 14:36         ` Clemens Ladisch
2005-04-27 16:56           ` Steve deRosier
2005-04-27 17:22             ` Clemens Ladisch
2005-04-27 20:31               ` Steve deRosier
2005-04-28  8:25                 ` Clemens Ladisch
2005-05-02 18:04                   ` Steve deRosier
2005-05-03  8:05                     ` Clemens Ladisch
     [not found] ` <ad2655cb0504270201165f9859@mail.gmail.com>
2005-04-27 16:43   ` Steve deRosier

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.