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

Reply via email to