Hello
I work at "hfkernel" by Tom Sailer, a program for pactor/rtty (soundcard ham
radio digimodes). It seems complicated, because it uses realtime scheduling,
select(), mmap(), and runs in 3 threads.
It was made in 1996 for OSS; I am trying to get it running with ALSA.
It is unique thing because it can do
Pactor without the expensive PTC (something like a radio modem),
may be of interest for many hams outside Europe /USA.
I and friends see messages like
" 512 fragments passed since last wakeup", in endless loop, leading to
crashes, seems to be xruns, not able to ctrl-alt-del, have to switch off
machine.
.
What do You think, how can ALSA support it, or Do I have to rewrite it for
ALSA.
I tried already with no success to say "Direct" and "non-block" in all
combinations to /proc/asound/card0/pcm0p etc...
If to rewrite, what function / ioctl matches
SNDCTL_DSP_GETISPACE...SNDCTL_DSP_GETOSPACE...
" ioctl(fd_audio, SNDCTL_DSP_GETIPTR, &cinfo) "
and
" ioctl(fd_audio, SNDCTL_DSP_GETOPTR, &cinfo) " ?
The prog is at https//projects.sourceforge.net/hfterm.
Here is one of the important functions out of l1/user/oss.c my prog:
Thanks for Your ideas!
*****************************************************************************/
/*
* oss.c -- Linux sound I/O.
*
* Copyright (C) 1997 Thomas Sailer ([EMAIL PROTECTED])
* Swiss Federal Institute of Technology (ETH), Electronics Lab
*
...
* This is the Linux realtime sound output driver
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <asm/byteorder.h>
#include <sys/soundcard.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <signal.h>
#include <endian.h>
#include <pthread.h>
#include "os.h"
#include "l1.h"
#include "l1user.h"
static int samples_remain = 0;
static int samples_count = 0;
static short *samples_ptr = NULL;
static int invert_ptt = 0;
static pthread_t thr_l1;
static float snd_corr;
#if __BYTE_ORDER == __BIG_ENDIAN
#define AUDIO_FMT AFMT_S16_BE
#else
#define AUDIO_FMT AFMT_S16_LE
#endif
static void *fdx_driver(void *name_audio)
{
size_t pagesize = getpagesize();
int apar, fd_audio, i;
union {
caddr_t v;
short *s;
} ibuf;
caddr_t ibuf_ext;
union {
caddr_t v;
short *s;
} obuf;
struct audio_buf_info iinfo, oinfo;
unsigned int isize, osize;
unsigned int ifragptr, ofragptr;
fd_set rmask, wmask;
struct count_info cinfo;
unsigned int curfrag, lastfrag, nfrags;
unsigned long long itime, otime, inc_fragment;
l1_time_t inc_sample;
int ptt_frames;
short *s;
if ((fd_audio = open(name_audio, O_RDWR, 0)) < 0)
errstr(SEV_FATAL, "open");
/*
* configure audio
*/
apar = AUDIO_FMT;
if (ioctl(fd_audio, SNDCTL_DSP_SETFMT, &apar) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETFMT");
if (apar != AUDIO_FMT)
errprintf(SEV_FATAL, "audio driver does not support the S16 format\n");
apar = 0;
if (ioctl(fd_audio, SNDCTL_DSP_STEREO, &apar) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_STEREO");
if (apar != 0)
errprintf(SEV_FATAL, "audio driver does not support mono\n");
apar = SAMPLE_RATE;
if (ioctl(fd_audio, SNDCTL_DSP_SPEED, &apar) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SPEED");
if (apar != SAMPLE_RATE) {
if (abs(apar-SAMPLE_RATE) >= SAMPLE_RATE/100)
errprintf(SEV_FATAL, "audio driver does not support 8kHz
sampling
frequency\n");
}
inc_sample = 1000000.0*snd_corr/apar;
inc_fragment = 64*1000000.0*snd_corr/apar*(1<<24);
ifragptr = 0;
itime = 0;
ofragptr = 1;
otime = ofragptr * inc_fragment;
ptt_frames = 0;
lastfrag = 0;
/*
* set fragment sizes
*/
apar = 0xffff0007U;
if (ioctl(fd_audio, SNDCTL_DSP_SETFRAGMENT, &apar) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETFRAGMENT");
if (ioctl(fd_audio, SNDCTL_DSP_GETOSPACE, &oinfo) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETOSPACE");
osize = oinfo.fragstotal * oinfo.fragsize;
if (ioctl(fd_audio, SNDCTL_DSP_GETISPACE, &iinfo) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETISPACE");
isize = iinfo.fragstotal * iinfo.fragsize;
if (EXCESS_FRAGS * iinfo.fragsize > pagesize)
errprintf(SEV_FATAL, "OSS: input: fragment size %d times excess frags
> page
size %d\n",
iinfo.fragsize, pagesize);
/*
* mmap buffers
*
* BSD people attention: you may need to uncomment the PROT_READ
* feedback welcome: [EMAIL PROTECTED]
*/
if ((ibuf.v = mmap(NULL, pagesize+isize, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED)
errstr(SEV_FATAL, "mmap: MAP_ANONYMOUS");
ibuf_ext = ibuf.v + isize;
if (munmap(ibuf.v, isize))
errstr(SEV_FATAL, "munmap: MAP_ANONYMOUS");
/* following line: '| PROT_WRITE ' helps against abort in my machine. Guenther
*/
if ((ibuf.v = mmap(ibuf.v, isize, PROT_READ | PROT_WRITE, MAP_FILE
| MAP_SHARED | MAP_FIXED,
fd_audio, 0)) == MAP_FAILED)
errstr(SEV_FATAL, "mmap: PROT_READ");
if ((obuf.v = mmap(NULL, osize, PROT_WRITE /* | PROT_READ*/,
MAP_FILE | MAP_SHARED, fd_audio, 0)) == MAP_FAILED)
errstr(SEV_FATAL, "mmap: PROT_WRITE");
errprintf(SEV_INFO, "OSS: output: #frag: %d fragsz: %d totbuf: %d bufaddr:
%p\n"
"OSS: input: #frag: %d fragsz: %d totbuf: %d bufaddr: %p
mempage:
%p\n"
"OSS: sample time increment: %u fragment time increment: %u\n",
oinfo.fragstotal, oinfo.fragsize, osize, obuf.s,
iinfo.fragstotal, iinfo.fragsize, isize, ibuf.s, ibuf_ext,
(unsigned int)inc_sample, (unsigned int)(inc_fragment >> 24));
/*
* start playback/recording
*/
apar = 0;
if (ioctl(fd_audio, SNDCTL_DSP_SETTRIGGER, &apar) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETTRIGGER");
apar = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;
if (ioctl(fd_audio, SNDCTL_DSP_SETTRIGGER, &apar) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETTRIGGER");
/*
* loop
*/
for (;;) {
FD_ZERO(&rmask);
FD_ZERO(&wmask);
FD_SET(fd_audio, &rmask);
FD_SET(fd_audio, &wmask);
i = select(fd_audio+1, &rmask, &wmask, NULL, NULL);
if (i < 0)
errstr(SEV_FATAL, "select");
if (!FD_ISSET(fd_audio, &rmask) && !FD_ISSET(fd_audio, &wmask))
continue;
/*
* process input
*/
if (ioctl(fd_audio, SNDCTL_DSP_GETIPTR, &cinfo) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETIPTR");
curfrag = cinfo.ptr / iinfo.fragsize;
if (cinfo.blocks > 2)
errprintf(SEV_WARNING, "%d fragments passed since last
wakeup\n",
cinfo.blocks);
while (ifragptr != curfrag) {
if (!ifragptr) {
s = (short *)(ibuf.v + isize + iinfo.fragsize *
ifragptr);
memcpy(s, ibuf.v + iinfo.fragsize * ifragptr,
iinfo.fragsize);
} else
s = (short *)(ibuf.v + iinfo.fragsize * ifragptr);
if (samples_remain > 0) {
i = 2*samples_remain;
if (i > iinfo.fragsize)
i = iinfo.fragsize;
memcpy(samples_ptr, s, i);
samples_ptr += i/2;
samples_remain -= i/2;
}
l1_input_samples(itime >> 24, inc_sample, s, iinfo.fragsize/2);
itime += inc_fragment;
ifragptr++;
if (ifragptr >= iinfo.fragstotal)
ifragptr = 0;
}
/*
* process output
*/
if (ioctl(fd_audio, SNDCTL_DSP_GETOPTR, &cinfo) == -1)
errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETOPTR");
curfrag = cinfo.ptr / oinfo.fragsize;
nfrags = oinfo.fragstotal + curfrag - lastfrag;
lastfrag = curfrag;
if (nfrags >= oinfo.fragstotal)
nfrags -= oinfo.fragstotal;
if (nfrags != cinfo.blocks)
errprintf(SEV_WARNING, "OSS sound driver lost interrupt!\n");
if (nfrags > 2)
errprintf(SEV_WARNING, "%d fragments passed since last
wakeup\n", nfrags);
ptt_frames -= nfrags;
if (ptt_frames < 0) {
otime += (-ptt_frames) * inc_fragment;
ofragptr -= ptt_frames;
while (ofragptr >= oinfo.fragstotal)
ofragptr -= oinfo.fragstotal;
ptt_frames = 0;
memset(obuf.s, 0, oinfo.fragsize * oinfo.fragstotal);
}
/* sanity check */
if (!ptt_frames && ofragptr != (curfrag + 1) % oinfo.fragstotal)
errprintf(SEV_FATAL, "output pointers inconsistent %u %u
%lu\n",
ofragptr, curfrag, (unsigned long)(otime >> 24));
while (ptt_frames < oinfo.fragstotal && ptt_frames <= 4 &&
l1_output_samples(otime >> 24, inc_sample, (short *)(obuf.v +
oinfo.fragsize * ofragptr),
oinfo.fragsize/2)) {
ofragptr++;
if (ofragptr >= oinfo.fragstotal)
ofragptr = 0;
ptt_frames++;
otime += inc_fragment;
}
output_ptt(ptt_frames > 0);
}
}
/* --------------------------------------------------------------------- */
G�nther
[EMAIL PROTECTED]
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel