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