The new Media Kit contains a compatibility interface which lets you use a pre-R4 sound card driver in R4 with only minor modifications to the driver. Here is a description of those modifications, assuming that you are starting with a driver written to the old API described in the Newsletter article:
http://www.be.com/aboutbe/benewsletter/volume_II/Issue22.htmlThe most important change is that the driver must publish a "sample clock" which allows the Media Kit to synchronize to the sound card. The sample clock corresponds to performance time measured by the DAC (or ADC) clock in microseconds. If the nominal sample rate is 44100 samples per second then the sample clock moves at (1000000 / 44100) microseconds per sample processed by the DAC (or ADC). If the DAC is actually processing 44109 samples per second than the DAC's sample clock will run slightly faster than real-time.
The sample clock is returned by the driver in the audio_buffer_header structure which now looks like this:
typedef struct audio_buffer_header { int32 buffer_number; int32 subscriber_count; bigtime_t time; int32 reserved_1 int32 reserved_2; bigtime_t sample_clock; } audio_buffer_header;
As before, the SOUND_WRITE_BUFFER
and SOUND_READ_BUFFER
ioctls should store an estimate of the system_time()
corresponding to the beginning of the buffer in the "time"
slot of the audio_buffer_header
. They should also fill the
"sample_clock
" slot with the sample clock for the beginning
of the buffer.
To calculate the sample clock, keep track of the number of samples processed and multiply by the sample clock rate:
header->sample_clock = (samples_processed * 1000000LL) / sample_rate;
As long as buffers are flowing continuously, the sample
clock will move at the same rate as the performance time of
the buffers. But if there is an interruption between buffers
then the sample clock must account for the length of the
interruption. One way to do this is to measure the duration
of the interruption and increment "samples_processed
" by the
number of samples that would have been played during that
time:
samples_processed += (time_skipped * sample_rate) / 1000000;
There are four new ioctl
codes which a driver may optionally
support to negotiate an optimal buffer size with the Media
Kit. They appear at the end of this list:
#includeenum { SOUND_GET_PARAMS = B_DEVICE_OP_CODES_END, SOUND_SET_PARAMS, SOUND_SET_PLAYBACK_COMPLETION_SEM, SOUND_SET_CAPTURE_COMPLETION_SEM, SOUND_RESERVED_1, /* unused */ SOUND_RESERVED_2, /* unused */ SOUND_DEBUG_ON, /* unused */ SOUND_DEBUG_OFF, /* unused */ SOUND_WRITE_BUFFER, SOUND_READ_BUFFER, SOUND_LOCK_FOR_DMA, SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE, SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE, SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE, SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE };
The SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE
and
SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE
ioctls
take an (int32
)
argument containing the buffer size (without the header)
that the Media Kit plans to send. If the driver is using a
circular DMA buffer it may want to set the size of the DMA
buffer to twice the preferred buffer size to minimize
latency.
The SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE
and
SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE
ioctls take an
(int32*
) argument in which the driver can return the current
setting of the preferred buffer size.
Devices supporting the above API should be published under
the "/dev/audio/old/
" directory where they will be found by
the "legacy" media add-on.
Adding a sample clock to your old R3 sound card driver will get it up and running again under R4.
Copyright ©1999 Be, Inc. Be is a registered trademark, and BeOS, BeBox, BeWare, GeekPort, the Be logo and the BeOS logo are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners.