openvortex-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Openvortex-dev] Re: [Alsa-devel] au8830+via & alsa 0.9.7c


From: Wilfried Weissmann
Subject: [Openvortex-dev] Re: [Alsa-devel] au8830+via & alsa 0.9.7c
Date: Sun, 23 Nov 2003 22:28:24 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020623 Debian/1.0.0-0.woody.1

Manuel Jander wrote:
This could be a period size bug. I didn't test the Alaw support myself,
but know i see that it could be useful for VoIP.

i just did some more testing after upgrading the libraries and utils to version 0.9.7 to get you some details. i recorded samples with arecord in mu-law mono with a sampling rate from 8khz to 48khz in 2khz steps. 8khz is fine. but the samples from 10khz to 32khz are getting worse with increased sampling rate (contrary to what i said before). 34khz to 48khz have perfect sound again. another funny thing is that at first i recorded a sample with 44100hz and then with 28000hz. and at the beginning of the 28000hz sample i found a low pitched snippet (due to the change is sampling rate) of the previous sample.


Sounds like a buffer problem. Some sizes miscalculated or some sort of
that. Maybe we are hitting an unknown design limitation ? Wouldn't be
the first time, since there is no "datasheet", only guesses and
"abtasten in der Dunkelheit" (don't know how to translate this, sorry).

i have written a small program that is cloned from the speakfreely sources to demonstrate the problem. now i think that the bug is not alaw/mulaw specific because of i can reproduce similar effects the with linear samples (with this program). the program tries to simulate voip traffic by sleeping between the playback of two samples. it should play a low pitched beep (called "silence"). then wait for a second before a long (5x) high pitched beep (called "beep") is played followed by a one second sleep. this is repeated 3 times.

        for(i=0; i<3; i++) {
                printf("start loop %d\n", i);
                soundplay(BUFFERSIZE(silence), silence);
                printf("pause loop %d\n", i);
                sleep(1);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                printf("end loop %d\n", i);
                sleep(1);
        }

but what i hear is quite different. the first time is OK:

a low beep, then a high beeeeeeeeeeeeeeep

afterwards i cannot hear a low beep. no sound for 2 seconds (1 second at the end of the loop + one after playing a low beep). then i hear two short high beeps (?!?).

adding or deleting some "soundplay(BUFFERSIZE(beep), beep);" produces different odd effects (total silence after the first loop, ...).

to run the program start it with:
$ ./soundbyte /dev/dsp /dev/mixer

this is quite similar to what i hear when i use speakfreely with silence suppression and/or experiencing network congestion. speakfreely is compiled with the "-DLINEAR" option to prevent it from using MULAW.


Best Regards

Manuel Jander

Greetings,
Wilfried
/*

        Sound interface for Speak Freely for Unix

        Designed and implemented in July of 1990 by John Walker

*/

#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#include <errno.h>

#include <sys/ioctl.h>

#include <linux/soundcard.h>

#define MAX_GAIN        100
#define SAMPLE_RATE 16000

static int audiof = -1;               /* Audio device file descriptor */
static int stereo=0;                  /* 0=mono, 1=stereo */
static int Audio_fd;                  /* Audio control port */

static int aubufsize = 2048;          /* Default */


/*  SOUNDINIT  --  Open the sound peripheral and initialise for
                   access.  Return TRUE if successful, FALSE
                   otherwise.  */

int soundinit(int iomode, char *devAudioOutput, char *devAudioControl)
{
    int attempts = 3;
    int format = AFMT_S16_LE;
    int speed = SAMPLE_RATE;
    int channels;
    int arg = 0x7FFF000B, frag_size;


    /* When opening the audio device file and control file, we
       check for a specification which begins with a sharp sign
       and, if present, use the integer which follows as the number
       of an already-open file descriptor.  This allows a launcher
       program to open the audio device and then fork two processes
       which invoke sfmike and sfspeaker.  Why go to all this
       trouble?  Because some audio drivers, particularly on
       Linux, don't permit two separate programs to open /dev/audio
       simultaneously, even though function just fine in full
       duplex.  This kludge allows getting aroung around that
       restriction. */

        audiof = open(devAudioOutput, iomode);

        if (audiof >= 0) {
            Audio_fd = open(devAudioControl, O_RDWR);
            if (Audio_fd < 0) {
                perror(devAudioControl);
                close(audiof);
                audiof = -1;
                return 0;
            }
    /*fcntl(audiof, F_SETFL, O_NDELAY);*/


   channels = 1;
   if (ioctl(audiof, SNDCTL_DSP_CHANNELS, &channels) == -1) {
     perror("SNDCTL_DSP_CHANNELS");
     exit(-1);
   }
   stereo = (channels==1)?0:1;
                {
                   int linearSet = 0;

                   if (ioctl(audiof, SNDCTL_DSP_SETFMT, &format) == -1) {
                      perror("SNDCTL_DSP_SETFMT");  
                   } else if (ioctl(audiof, SNDCTL_DSP_STEREO, &stereo) == -1) {
                      perror("SNDCTL_DSP_STEREO");
                   } else if (ioctl(audiof, SNDCTL_DSP_SPEED, &speed) == -1) {
                      perror("SNDCTL_DSP_SPEED");  
                   } else {
                      linearSet = 1;
                   }
                   if (!linearSet) {
                      soundterm();
                      return 0;
                   }
                }
            if (ioctl(audiof, SNDCTL_DSP_NONBLOCK, NULL) < 0) {
                perror("SNDCTL_DSP_NONBLOCK");
                soundterm();
                return 0;
            }

        if (ioctl(audiof, SNDCTL_DSP_SETFRAGMENT, &arg) == -1) {
           /* Ignore EINVAL if we were handed an open file descriptor
              because that just means that sound is already being
              transferred, which, in turn, means that another process
              has already configured the device.
           */
           if ((errno != EINVAL)) {
              perror("SNDCTL_DSP_SETFRAGMENT (LINUX_DSP_SMALL_BUFFER defined)");
           }
           /* This isn't fatal, so keep on going. */
        }
        if (ioctl(audiof, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) {
            perror("SNDCTL_DSP_GETBLKSIZE (LINUX_DSP_SMALL_BUFFER defined)");
            soundterm();
            return 0;
        }
    
    }
    return 0;
}

/*  SOUNDTERM  --  Close the sound device.  */

void soundterm(void)
{
            if (close(audiof) < 0) {
                perror("closing audio device");
            }
            if (close(Audio_fd) < 0) {
                perror("closing audio control device");
            }
            audiof = -1;
}

/*  SOUNDPLAY  --  Begin playing a sound.  */

void soundplay(int len, short int *buf)
{
    int ios;

    //fprintf(stderr, "sound: writing %d bytes\n", len);
    while (1) {
        ios = write(audiof, buf, len);
        //fprintf(stderr, "sound: wrote %d of %d bytes\n", ios, len);
        if (ios == -1) {
        } else {
            if (ios < len) {
                buf += ios;
                len -= ios;
            } else {
                break;
            }
        }
    }
    //fprintf(stderr, "sound: done\n");
}

short int beep[2048];
short int silence[2048];

#define BUFFERSIZE(what) (sizeof(what)/sizeof(short int))

//#define sleep(x)

int main(int argc, char ** argv) {
        int i;
        for(i=0; i<BUFFERSIZE(beep); i++) {
                beep[i]=sin(( i*2160/BUFFERSIZE(beep) )/4)*16000;
        }
        for(i=0; i<BUFFERSIZE(silence); i++) {
                silence[i]=sin(( i*2160/BUFFERSIZE(beep) )/8)*16000;
        }
        soundinit(O_RDWR, argv[1], argv[2]);
        //soundplay(BUFFERSIZE(beep), beep);
        for(i=0; i<3; i++) {
                printf("start loop %d\n", i);
                soundplay(BUFFERSIZE(silence), silence);
                printf("pause loop %d\n", i);
                sleep(1);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                soundplay(BUFFERSIZE(beep), beep);
                printf("end loop %d\n", i);
                sleep(1);
        }
}
all:
        gcc -lm soundbyte.c -o soundbyte

reply via email to

[Prev in Thread] Current Thread [Next in Thread]