static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { audio_info_t info; AUDIO_INITINFO(&info); if (mode != O_RDONLY) { info.play.sample_rate = ss->rate; info.play.channels = ss->channels; switch (ss->format) { case PA_SAMPLE_U8: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_LINEAR; break; case PA_SAMPLE_ALAW: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_ALAW; break; case PA_SAMPLE_ULAW: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_ULAW; break; case PA_SAMPLE_S16NE: info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; break; default: return -1; } } if (mode != O_WRONLY) { info.record.sample_rate = ss->rate; info.record.channels = ss->channels; switch (ss->format) { case PA_SAMPLE_U8: info.record.precision = 8; info.record.encoding = AUDIO_ENCODING_LINEAR; break; case PA_SAMPLE_ALAW: info.record.precision = 8; info.record.encoding = AUDIO_ENCODING_ALAW; break; case PA_SAMPLE_ULAW: info.record.precision = 8; info.record.encoding = AUDIO_ENCODING_ULAW; break; case PA_SAMPLE_S16NE: info.record.precision = 16; info.record.encoding = AUDIO_ENCODING_LINEAR; break; default: return -1; } } if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) pa_log("AUDIO_SETINFO: Unsupported sample format."); else pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } return 0; }
/********************************************************************* * Try to open the named device. * If it opens, try to set various rates and formats and fill in * the device info structure. */ PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad ) { int result = paHostError; int tempDevHandle; int numChannels, maxNumChannels; int numSampleRates; int sampleRate; int numRatesToTry; int ratesToTry[9] = {96000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; int i; audio_info_t solaris_info; audio_device_t device_info; /* douglas: we have to do this querying in a slightly different order. apparently some sound cards will give you different info based on their settins. e.g. a card might give you stereo at 22kHz but only mono at 44kHz. the correct order for OSS is: format, channels, sample rate */ /* to check a device for it's capabilities, it's probably better to use the equivalent "-ctl"-descriptor - MR */ char devname[strlen(deviceName) + 4]; snprintf(devname,(strlen(deviceName) + 4),"%sctl",deviceName); if ((tempDevHandle = open(devname, O_WRONLY|O_NONBLOCK)) == -1 ) { DBUG(("Pa_QueryDevice: could not open %s\n", deviceName )); return paHostError; } /* Ask OSS what formats are supported by the hardware. */ pad->pad_Info.nativeSampleFormats = 0; AUDIO_INITINFO(&solaris_info); /* SAM 12/31/01: Sparc native does mulaw, alaw and PCM. I think PCM is signed. */ for (i = 8; i <= 32; i += 8) { solaris_info.play.precision = i; solaris_info.play.encoding = AUDIO_ENCODING_LINEAR; /* If there are no errors, add the format. */ if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) > -1) { switch (i) { case 8: pad->pad_Info.nativeSampleFormats |= paInt8; break; case 16: pad->pad_Info.nativeSampleFormats |= paInt16; break; case 24: pad->pad_Info.nativeSampleFormats |= paInt24; break; case 32: pad->pad_Info.nativeSampleFormats |= paInt32; break; } } } maxNumChannels = 0; for( numChannels = 1; numChannels <= 16; numChannels++ ) { int temp = numChannels; DBUG(("Pa_QueryDevice: use SNDCTL_DSP_CHANNELS, numChannels = %d\n", numChannels )) AUDIO_INITINFO(&solaris_info); solaris_info.play.channels = temp; if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) < 0) { /* ioctl() failed so bail out if we already have stereo */ if( numChannels > 2 ) break; } else { /* ioctl() worked but bail out if it does not support numChannels. * We don't want to leave gaps in the numChannels supported. */ if( (numChannels > 2) && (temp != numChannels) ) break; DBUG(("Pa_QueryDevice: temp = %d\n", temp )) if( temp > maxNumChannels ) maxNumChannels = temp; /* Save maximum. */ } } pad->pad_Info.maxOutputChannels = maxNumChannels; DBUG(("Pa_QueryDevice: maxNumChannels = %d\n", maxNumChannels)) /* FIXME - for now, assume maxInputChannels = maxOutputChannels. * Eventually do separate queries for O_WRONLY and O_RDONLY */ pad->pad_Info.maxInputChannels = pad->pad_Info.maxOutputChannels; DBUG(("Pa_QueryDevice: maxInputChannels = %d\n", pad->pad_Info.maxInputChannels)) /* Determine available sample rates by trying each one and seeing result. */ numSampleRates = 0; AUDIO_INITINFO(&solaris_info); numRatesToTry = sizeof(ratesToTry)/sizeof(int); for (i = 0; i < numRatesToTry; i++) { sampleRate = ratesToTry[i]; solaris_info.play.sample_rate = sampleRate; /* AS: We opened for Write, so set play */ if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) >= 0 ) /* PLB20010817 */ { if (sampleRate == ratesToTry[i]) { DBUG(("Pa_QueryDevice: got sample rate: %d\n", sampleRate)) pad->pad_SampleRates[numSampleRates] = (float)ratesToTry[i]; numSampleRates++; } } } DBUG(("Pa_QueryDevice: final numSampleRates = %d\n", numSampleRates)) if (numSampleRates==0) /* HP20010922 */ { ERR_RPT(("Pa_QueryDevice: no supported sample rate (or SNDCTL_DSP_SPEED ioctl call failed).\n" )); goto error; } pad->pad_Info.numSampleRates = numSampleRates; pad->pad_Info.sampleRates = pad->pad_SampleRates; /* query for the device name instead of using the filesystem-device - MR */ if (ioctl(tempDevHandle, AUDIO_GETDEV, &device_info) == -1) { pad->pad_Info.name = deviceName; } else { char *pt = (char *)PaHost_AllocateFastMemory(strlen(device_info.name)); strcpy(pt, device_info.name); pad->pad_Info.name = pt; } result = paNoError; error: /* We MUST close the handle here or we won't be able to reopen it later!!! */ close(tempDevHandle); return result; }
static void input_sound(unsigned int sample_rate, unsigned int overlap, const char *ifname) { audio_info_t audioinfo; audio_info_t audioinfo2; audio_device_t audiodev; int fd; short buffer[8192]; float fbuf[16384]; unsigned int fbuf_cnt = 0; int i; short *sp; if ((fd = open(ifname ? ifname : "/dev/audio", O_RDONLY)) < 0) { perror("open"); exit (10); } if (ioctl(fd, AUDIO_GETDEV, &audiodev) == -1) { perror("ioctl: AUDIO_GETDEV"); exit (10); } AUDIO_INITINFO(&audioinfo); audioinfo.record.sample_rate = sample_rate; audioinfo.record.channels = 1; audioinfo.record.precision = 16; audioinfo.record.encoding = AUDIO_ENCODING_LINEAR; /*audioinfo.record.gain = 0x20; audioinfo.record.port = AUDIO_LINE_IN; audioinfo.monitor_gain = 0;*/ if (ioctl(fd, AUDIO_SETINFO, &audioinfo) == -1) { perror("ioctl: AUDIO_SETINFO"); exit (10); } if (ioctl(fd, I_FLUSH, FLUSHR) == -1) { perror("ioctl: I_FLUSH"); exit (10); } if (ioctl(fd, AUDIO_GETINFO, &audioinfo2) == -1) { perror("ioctl: AUDIO_GETINFO"); exit (10); } fprintf(stdout, "Audio device: name %s, ver %s, config %s, " "sampling rate %d\n", audiodev.name, audiodev.version, audiodev.config, audioinfo.record.sample_rate); for (;;) { i = read(fd, sp = buffer, sizeof(buffer)); if (i < 0 && errno != EAGAIN) { perror("read"); exit(4); } if (!i) break; if (i > 0) { if(integer_only) { fbuf_cnt = i/sizeof(buffer[0]); } else { for (; i >= sizeof(buffer[0]); i -= sizeof(buffer[0]), sp++) fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0); if (i) fprintf(stderr, "warning: noninteger number of samples read\n"); } if (fbuf_cnt > overlap) { process_buffer(fbuf, buffer, fbuf_cnt-overlap); memmove(fbuf, fbuf+fbuf_cnt-overlap, overlap*sizeof(fbuf[0])); fbuf_cnt = overlap; } } } close(fd); }
static int SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); SDL_AudioFormat format = 0; audio_info_t info; /* We don't care what the devname is...we'll try to open anything. */ /* ...but default to first name in the list... */ if (devname == NULL) { devname = SDL_GetAudioDeviceName(0, iscapture); if (devname == NULL) { return SDL_SetError("No such audio device"); } } /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); if (this->hidden == NULL) { return SDL_OutOfMemory(); } SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Open the audio device */ this->hidden->audio_fd = open(devname, flags, 0); if (this->hidden->audio_fd < 0) { return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); } #ifdef AUDIO_SETINFO int enc; #endif int desired_freq = this->spec.freq; /* Determine the audio parameters from the AudioSpec */ switch (SDL_AUDIO_BITSIZE(this->spec.format)) { case 8: { /* Unsigned 8 bit audio data */ this->spec.format = AUDIO_U8; #ifdef AUDIO_SETINFO enc = AUDIO_ENCODING_LINEAR8; #endif } break; case 16: { /* Signed 16 bit audio data */ this->spec.format = AUDIO_S16SYS; #ifdef AUDIO_SETINFO enc = AUDIO_ENCODING_LINEAR; #endif } break; default: { /* !!! FIXME: fallback to conversion on unsupported types! */ return SDL_SetError("Unsupported audio format"); } } this->hidden->audio_fmt = this->spec.format; this->hidden->ulaw_only = 0; /* modern Suns do support linear audio */ #ifdef AUDIO_SETINFO for (;;) { audio_info_t info; AUDIO_INITINFO(&info); /* init all fields to "no change" */ /* Try to set the requested settings */ info.play.sample_rate = this->spec.freq; info.play.channels = this->spec.channels; info.play.precision = (enc == AUDIO_ENCODING_ULAW) ? 8 : this->spec.format & 0xff; info.play.encoding = enc; if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) { /* Check to be sure we got what we wanted */ if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) { return SDL_SetError("Error getting audio parameters: %s", strerror(errno)); } if (info.play.encoding == enc && info.play.precision == (this->spec.format & 0xff) && info.play.channels == this->spec.channels) { /* Yow! All seems to be well! */ this->spec.freq = info.play.sample_rate; break; } } switch (enc) { case AUDIO_ENCODING_LINEAR8: /* unsigned 8bit apparently not supported here */ enc = AUDIO_ENCODING_LINEAR; this->spec.format = AUDIO_S16SYS; break; /* try again */ case AUDIO_ENCODING_LINEAR: /* linear 16bit didn't work either, resort to µ-law */ enc = AUDIO_ENCODING_ULAW; this->spec.channels = 1; this->spec.freq = 8000; this->spec.format = AUDIO_U8; this->hidden->ulaw_only = 1; break; default: /* oh well... */ return SDL_SetError("Error setting audio parameters: %s", strerror(errno)); } } #endif /* AUDIO_SETINFO */ this->hidden->written = 0; /* We can actually convert on-the-fly to U-Law */ if (this->hidden->ulaw_only) { this->spec.freq = desired_freq; this->hidden->fragsize = (this->spec.samples * 1000) / (this->spec.freq / 8); this->hidden->frequency = 8; this->hidden->ulaw_buf = (Uint8 *) SDL_malloc(this->hidden->fragsize); if (this->hidden->ulaw_buf == NULL) { return SDL_OutOfMemory(); } this->spec.channels = 1; } else { this->hidden->fragsize = this->spec.samples; this->hidden->frequency = this->spec.freq / 1000; } #ifdef DEBUG_AUDIO fprintf(stderr, "Audio device %s U-Law only\n", this->hidden->ulaw_only ? "is" : "is not"); fprintf(stderr, "format=0x%x chan=%d freq=%d\n", this->spec.format, this->spec.channels, this->spec.freq); #endif /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(&this->spec); /* Allocate mixing buffer */ this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->spec.size); if (this->hidden->mixbuf == NULL) { return SDL_OutOfMemory(); } SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* We're ready to rock and roll. :-) */ return 0; }
FILE *out_file_open(char *outFile, int rate, int *channels) { FILE *fout=NULL; /*Open output file*/ if (strlen(outFile)==0) { #if defined HAVE_SYS_SOUNDCARD_H int audio_fd, format, stereo; audio_fd=open("/dev/dsp", O_WRONLY); if (audio_fd<0) { perror("Cannot open /dev/dsp"); exit(1); } format=AFMT_S16_NE; // format=AFMT_S16_LE; if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1) { perror("SNDCTL_DSP_SETFMT"); close(audio_fd); exit(1); } stereo=0; if (*channels==2) stereo=1; if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1) { perror("SNDCTL_DSP_STEREO"); close(audio_fd); exit(1); } if (stereo!=0) { if (*channels==1) fprintf (stderr, "Cannot set mono mode, will decode in stereo\n"); *channels=2; } if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate)==-1) { perror("SNDCTL_DSP_SPEED"); close(audio_fd); exit(1); } fout = fdopen(audio_fd, "w"); printf ("/dev/dsp opened"); #elif defined HAVE_SYS_AUDIOIO_H audio_info_t info; int audio_fd; audio_fd = open("/dev/audio", O_WRONLY); if (audio_fd<0) { perror("Cannot open /dev/audio"); exit(1); } AUDIO_INITINFO(&info); #ifdef AUMODE_PLAY /* NetBSD/OpenBSD */ info.mode = AUMODE_PLAY; #endif info.play.encoding = AUDIO_ENCODING_SLINEAR; info.play.precision = 16; info.play.sample_rate = rate; info.play.channels = *channels; if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { perror ("AUDIO_SETINFO"); exit(1); } fout = fdopen(audio_fd, "w"); #elif defined WIN32 || defined _WIN32 { unsigned int speex_channels = *channels; if (Set_WIN_Params (INVALID_FILEDESC, rate, SAMPLE_SIZE, speex_channels)) { fprintf (stderr, "Can't access %s\n", "WAVE OUT"); exit(1); } } #else fprintf (stderr, "No soundcard support\n"); exit(1); #endif } return fout; }
static int sio_sun_setpar(struct sio_hdl *sh, struct sio_par *par) { #define NRETRIES 8 struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; struct audio_info aui; unsigned int i, infr, ibpf, onfr, obpf; unsigned int bufsz, round; unsigned int rate, req_rate, prec, enc; /* * try to set parameters until the device accepts * a common encoding and rate for play and record */ rate = par->rate; prec = par->bits; sio_sun_enctoinfo(hdl, &enc, par); for (i = 0;; i++) { if (i == NRETRIES) { DPRINTF("sio_sun_setpar: couldn't set parameters\n"); hdl->sio.eof = 1; return 0; } AUDIO_INITINFO(&aui); if (hdl->sio.mode & SIO_PLAY) { aui.play.sample_rate = rate; aui.play.precision = prec; aui.play.encoding = enc; aui.play.channels = par->pchan; } if (hdl->sio.mode & SIO_REC) { aui.record.sample_rate = rate; aui.record.precision = prec; aui.record.encoding = enc; aui.record.channels = par->rchan; } DPRINTFN(2, "sio_sun_setpar: %i: trying pars = %u/%u/%u\n", i, rate, prec, enc); if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0 && errno != EINVAL) { DPERROR("sio_sun_setpar: setinfo(pars)"); hdl->sio.eof = 1; return 0; } if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { DPERROR("sio_sun_setpar: getinfo(pars)"); hdl->sio.eof = 1; return 0; } enc = (hdl->sio.mode & SIO_REC) ? aui.record.encoding : aui.play.encoding; switch (enc) { case AUDIO_ENCODING_SLINEAR_LE: case AUDIO_ENCODING_SLINEAR_BE: case AUDIO_ENCODING_ULINEAR_LE: case AUDIO_ENCODING_ULINEAR_BE: case AUDIO_ENCODING_SLINEAR: case AUDIO_ENCODING_ULINEAR: break; default: DPRINTF("sio_sun_setpar: couldn't set linear encoding\n"); hdl->sio.eof = 1; return 0; } if (hdl->sio.mode != (SIO_REC | SIO_PLAY)) break; if (aui.play.sample_rate == aui.record.sample_rate && aui.play.precision == aui.record.precision && aui.play.encoding == aui.record.encoding) break; if (i < NRETRIES / 2) { rate = aui.play.sample_rate; prec = aui.play.precision; enc = aui.play.encoding; } else { rate = aui.record.sample_rate; prec = aui.record.precision; enc = aui.record.encoding; } } /* * If the rate that the hardware is using is different than * the requested rate, scale buffer sizes so they will be the * same time duration as what was requested. This just gets * the rates to use for scaling, that actual scaling is done * later. */ rate = (hdl->sio.mode & SIO_REC) ? aui.record.sample_rate : aui.play.sample_rate; req_rate = rate; if (par->rate && par->rate != ~0U) req_rate = par->rate; /* * if block size and buffer size are not both set then * set the blocksize to half the buffer size */ bufsz = par->appbufsz; round = par->round; if (bufsz != ~0U) { bufsz = bufsz * rate / req_rate; if (round == ~0U) round = (bufsz + 1) / 2; else round = round * rate / req_rate; } else if (round != ~0U) { round = round * rate / req_rate; bufsz = round * 2; } else return 1; /* * get the play/record frame size in bytes */ if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { DPERROR("sio_sun_setpar: GETINFO"); hdl->sio.eof = 1; return 0; } ibpf = (hdl->sio.mode & SIO_REC) ? aui.record.channels * aui.record.bps : 1; obpf = (hdl->sio.mode & SIO_PLAY) ? aui.play.channels * aui.play.bps : 1; DPRINTFN(2, "sio_sun_setpar: bpf = (%u, %u)\n", ibpf, obpf); /* * try to set parameters until the device accepts * a common block size for play and record */ for (i = 0; i < NRETRIES; i++) { AUDIO_INITINFO(&aui); aui.hiwat = (bufsz + round - 1) / round; aui.lowat = aui.hiwat; if (hdl->sio.mode & SIO_REC) aui.record.block_size = round * ibpf; if (hdl->sio.mode & SIO_PLAY) aui.play.block_size = round * obpf; if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0) { DPERROR("sio_sun_setpar2: SETINFO"); hdl->sio.eof = 1; return 0; } if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { DPERROR("sio_sun_setpar2: GETINFO"); hdl->sio.eof = 1; return 0; } infr = aui.record.block_size / ibpf; onfr = aui.play.block_size / obpf; DPRINTFN(2, "sio_sun_setpar: %i: trying round = %u -> (%u, %u)\n", i, round, infr, onfr); /* * if half-duplex or both block sizes match, we're done */ if (hdl->sio.mode != (SIO_REC | SIO_PLAY) || infr == onfr) { DPRINTFN(2, "sio_sun_setpar: blocksize ok\n"); return 1; } /* * half of the retries, retry with the smaller value, * then with the larger returned value */ if (i < NRETRIES / 2) round = infr < onfr ? infr : onfr; else round = infr < onfr ? onfr : infr; } DPRINTFN(2, "sio_sun_setpar: couldn't find a working blocksize\n"); hdl->sio.eof = 1; return 0; #undef NRETRIES }
//PORTING: This function contains a ton of OS specific stuff. Hack and // slash at will. Error SoundCardPMO::Init(OutputInfo * info) { m_properlyInitialized = false; if (!info) { info = myInfo; } else { // got info, so this is the beginning... if ((audio_fd = open("/dev/audio", O_WRONLY, 0)) < 0) { if (errno == EBUSY) { ReportError("Audio device is busy. Please make sure that " "another program is not using the device."); return (Error) pmoError_DeviceOpenFailed; } else { ReportError("Cannot open audio device. Please make sure that " "the audio device is properly configured."); return (Error) pmoError_DeviceOpenFailed; } } m_iDataSize = info->max_buffer_size; } int fd = audio_fd; struct audio_info ainfo; if (ioctl(audio_fd, AUDIO_GETINFO, &ainfo) < 0) { ReportError("Cannot get the flags on the audio device."); return (Error) pmoError_IOCTL_F_GETFL; } audio_fd = fd; channels = info->number_of_channels; for (unsigned int i = 0; i < info->number_of_channels; ++i) bufferp[i] = buffer + i; // configure the device: int play_precision = 16; // int play_stereo = channels - 1; int play_sample_rate = info->samples_per_second; if (ioctl(audio_fd, I_FLUSH, FLUSHRW) == -1) { ReportError("Cannot reset the soundcard."); return (Error) pmoError_IOCTL_SNDCTL_DSP_RESET; } AUDIO_INITINFO(&ainfo); ainfo.play.precision = play_precision; ainfo.play.channels = channels; ainfo.play.sample_rate = play_sample_rate; ainfo.play.encoding = AUDIO_ENCODING_LINEAR; if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo) == -1) { ReportError("Cannot set the soundcard's sampling speed."); return (Error) pmoError_IOCTL_SNDCTL_DSP_SPEED; } myInfo->bits_per_sample = info->bits_per_sample; myInfo->number_of_channels = info->number_of_channels; myInfo->samples_per_second = info->samples_per_second; myInfo->max_buffer_size = info->max_buffer_size; m_properlyInitialized = true; // PORTING: The GETOSPACE ioctl determines how much space the kernel's // output buffer has. Your OS may not have this. m_iTotalFragments = 2048; /* An arbitrary value of 2048. */ m_iOutputBufferSize = play_precision * m_iTotalFragments; m_iBytesPerSample = info->number_of_channels * (info->bits_per_sample / 8); return kError_NoErr; }
/* * Initialize the audio device. * This routine must set the following external variables: * rplay_audio_sample_rate * rplay_audio_precision * rplay_audio_channels * rplay_audio_format * rplay_audio_port * * and may use the following optional parameters: * optional_sample_rate * optional_precision * optional_channels * optional_format * optional_port * * optional_* variables with values of zero should be ignored. * * Return 0 on success and -1 on error. */ int rplay_audio_init() { audio_info_t a; audio_device_t d; if (rplay_audio_fd == -1) { rplay_audio_open(); if (rplay_audio_fd == -1) { report(REPORT_ERROR, "rplay_audio_init: cannot open %s\n", rplay_audio_device); return -1; } } if (ioctl(rplay_audio_fd, AUDIO_GETDEV, &d) < 0) { report(REPORT_ERROR, "rplay_audio_init: AUDIO_GETDEV: %s\n", sys_err_str(errno)); return -1; } if (strcmp(d.name, "SUNW,dbri") == 0) { report(REPORT_DEBUG, "%s device detected\n", d.name); rplay_audio_sample_rate = optional_sample_rate ? optional_sample_rate : 11025; rplay_audio_precision = optional_precision ? optional_precision : 16; rplay_audio_channels = optional_channels ? optional_channels : 1; rplay_audio_format = optional_format ? optional_format : rplay_audio_precision == 16 ? RPLAY_FORMAT_LINEAR_16 : RPLAY_FORMAT_LINEAR_8; rplay_audio_port = optional_port ? optional_port : RPLAY_AUDIO_PORT_LINEOUT | RPLAY_AUDIO_PORT_SPEAKER; rplay_audio_table = dbri_table; } else if (strcmp(d.name, "SUNW,CS4231") == 0) { report(REPORT_DEBUG, "%s device detected\n", d.name); rplay_audio_sample_rate = optional_sample_rate ? optional_sample_rate : 11025; rplay_audio_precision = optional_precision ? optional_precision : 16; rplay_audio_channels = optional_channels ? optional_channels : 1; rplay_audio_format = optional_format ? optional_format : rplay_audio_precision == 16 ? RPLAY_FORMAT_LINEAR_16 : RPLAY_FORMAT_LINEAR_8; rplay_audio_port = optional_port ? optional_port : RPLAY_AUDIO_PORT_LINEOUT | RPLAY_AUDIO_PORT_SPEAKER; rplay_audio_table = dbri_table; /* use the dbri table */ } else if (strcmp(d.name, "SUNW,am79c30") == 0) { report(REPORT_DEBUG, "%s device detected\n", d.name); rplay_audio_sample_rate = optional_sample_rate ? optional_sample_rate : 8000; rplay_audio_precision = optional_precision ? optional_precision : 8; rplay_audio_channels = optional_channels ? optional_channels : 1; rplay_audio_format = optional_format ? optional_format : RPLAY_FORMAT_ULAW; rplay_audio_port = optional_port ? optional_port : RPLAY_AUDIO_PORT_SPEAKER; rplay_audio_table = amd_table; } else if (strcmp(d.name, "SUNW,sb16") == 0) { report(REPORT_DEBUG, "%s device detected\n", d.name); rplay_audio_sample_rate = optional_sample_rate ? optional_sample_rate : 44100; rplay_audio_precision = optional_precision ? optional_precision : 16; rplay_audio_channels = optional_channels ? optional_channels : 2; rplay_audio_format = optional_format ? optional_format : rplay_audio_precision == 16 ? RPLAY_FORMAT_LINEAR_16 : RPLAY_FORMAT_LINEAR_8; rplay_audio_port = optional_port ? optional_port : RPLAY_AUDIO_PORT_LINEOUT | RPLAY_AUDIO_PORT_SPEAKER; rplay_audio_table = dbri_table; /* use the dbri table */ } else { report(REPORT_ERROR, "`%s' unknown audio device detected\n", d.name); return -1; } /* Verify the precision and format. */ switch (rplay_audio_precision) { case 8: if (rplay_audio_format != RPLAY_FORMAT_ULAW && rplay_audio_format != RPLAY_FORMAT_LINEAR_8) { report(REPORT_ERROR, "rplay_audio_init: can't use %d bits with format=%d\n", rplay_audio_precision, rplay_audio_format); return -1; } break; case 16: if (rplay_audio_format != RPLAY_FORMAT_LINEAR_16) { report(REPORT_ERROR, "rplay_audio_init: can't use %d bits with format=%d\n", rplay_audio_precision, rplay_audio_format); return -1; } break; default: report(REPORT_ERROR, "rplay_audio_init: `%d' unsupported audio precision\n", rplay_audio_precision); return -1; } AUDIO_INITINFO(&a); switch (rplay_audio_format) { case RPLAY_FORMAT_ULAW: a.play.encoding = AUDIO_ENCODING_ULAW; break; case RPLAY_FORMAT_LINEAR_8: case RPLAY_FORMAT_LINEAR_16: a.play.encoding = AUDIO_ENCODING_LINEAR; break; default: report(REPORT_ERROR, "rplay_audio_init: unsupported audio format `%d'\n", rplay_audio_format); return -1; } /* Audio port. */ if (rplay_audio_port == RPLAY_AUDIO_PORT_NONE) { a.play.port = ~0; /* see AUDIO_INITINFO in /usr/include/sys/audioio.h. */ } else { a.play.port = 0; if (BIT(rplay_audio_port, RPLAY_AUDIO_PORT_LINEOUT)) { #ifdef AUDIO_LINE_OUT SET_BIT(a.play.port, AUDIO_LINE_OUT); #else CLR_BIT(rplay_audio_port, RPLAY_AUDIO_PORT_LINEOUT); #endif } if (BIT(rplay_audio_port, RPLAY_AUDIO_PORT_HEADPHONE)) { #ifdef AUDIO_HEADPHONE SET_BIT(a.play.port, AUDIO_HEADPHONE); #else CLR_BIT(rplay_audio_port, RPLAY_AUDIO_PORT_HEADPHONE); #endif } if (BIT(rplay_audio_port, RPLAY_AUDIO_PORT_SPEAKER)) { #ifdef AUDIO_SPEAKER SET_BIT(a.play.port, AUDIO_SPEAKER); #endif /* Assume speaker is okay. */ } } a.play.sample_rate = rplay_audio_sample_rate; a.play.precision = rplay_audio_precision; a.play.channels = rplay_audio_channels; if (ioctl(rplay_audio_fd, AUDIO_SETINFO, &a) < 0) { report(REPORT_ERROR, "rplay_audio_init: AUDIO_SETINFO: %s\n", sys_err_str(errno)); return -1; } return 0; }
int DSP_OpenAudio(_THIS, SDL_AudioSpec * spec) { char audiodev[1024]; #ifdef AUDIO_SETINFO int enc; #endif int desired_freq = spec->freq; /* Initialize our freeable variables, in case we fail */ audio_fd = -1; mixbuf = NULL; ulaw_buf = NULL; /* Determine the audio parameters from the AudioSpec */ switch (SDL_AUDIO_BITSIZE(spec->format)) { case 8: { /* Unsigned 8 bit audio data */ spec->format = AUDIO_U8; #ifdef AUDIO_SETINFO enc = AUDIO_ENCODING_LINEAR8; #endif } break; case 16: { /* Signed 16 bit audio data */ spec->format = AUDIO_S16SYS; #ifdef AUDIO_SETINFO enc = AUDIO_ENCODING_LINEAR; #endif } break; default: { /* !!! FIXME: fallback to conversion on unsupported types! */ SDL_SetError("Unsupported audio format"); return (-1); } } audio_fmt = spec->format; /* Open the audio device */ audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 1); if (audio_fd < 0) { SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); return (-1); } ulaw_only = 0; /* modern Suns do support linear audio */ #ifdef AUDIO_SETINFO for (;;) { audio_info_t info; AUDIO_INITINFO(&info); /* init all fields to "no change" */ /* Try to set the requested settings */ info.play.sample_rate = spec->freq; info.play.channels = spec->channels; info.play.precision = (enc == AUDIO_ENCODING_ULAW) ? 8 : spec->format & 0xff; info.play.encoding = enc; if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0) { /* Check to be sure we got what we wanted */ if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { SDL_SetError("Error getting audio parameters: %s", strerror(errno)); return -1; } if (info.play.encoding == enc && info.play.precision == (spec->format & 0xff) && info.play.channels == spec->channels) { /* Yow! All seems to be well! */ spec->freq = info.play.sample_rate; break; } } switch (enc) { case AUDIO_ENCODING_LINEAR8: /* unsigned 8bit apparently not supported here */ enc = AUDIO_ENCODING_LINEAR; spec->format = AUDIO_S16SYS; break; /* try again */ case AUDIO_ENCODING_LINEAR: /* linear 16bit didn't work either, resort to µ-law */ enc = AUDIO_ENCODING_ULAW; spec->channels = 1; spec->freq = 8000; spec->format = AUDIO_U8; ulaw_only = 1; break; default: /* oh well... */ SDL_SetError("Error setting audio parameters: %s", strerror(errno)); return -1; } } #endif /* AUDIO_SETINFO */ written = 0; /* We can actually convert on-the-fly to U-Law */ if (ulaw_only) { spec->freq = desired_freq; fragsize = (spec->samples * 1000) / (spec->freq / 8); frequency = 8; ulaw_buf = (Uint8 *) SDL_malloc(fragsize); if (ulaw_buf == NULL) { SDL_OutOfMemory(); return (-1); } spec->channels = 1; } else { fragsize = spec->samples; frequency = spec->freq / 1000; } #ifdef DEBUG_AUDIO fprintf(stderr, "Audio device %s U-Law only\n", ulaw_only ? "is" : "is not"); fprintf(stderr, "format=0x%x chan=%d freq=%d\n", spec->format, spec->channels, spec->freq); #endif /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(spec); /* Allocate mixing buffer */ mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size); if (mixbuf == NULL) { SDL_OutOfMemory(); return (-1); } SDL_memset(mixbuf, spec->silence, spec->size); /* We're ready to rock and roll. :-) */ return (0); }
void xf86OSRingBell(int loudness, int pitch, int duration) { static short samples[BELL_SAMPLES]; static short silence[BELL_SAMPLES]; /* "The Sound of Silence" */ static int lastFreq; int cnt; int i; int written; int repeats; int freq; audio_info_t audioInfo; struct iovec iov[IOV_MAX]; int iovcnt; double ampl, cyclen, phase; int audioFD; if ((loudness <= 0) || (pitch <= 0) || (duration <= 0)) { return; } lastFreq = 0; memset(silence, 0, sizeof(silence)); audioFD = open(AUDIO_DEVICE, O_WRONLY | O_NONBLOCK); if (audioFD == -1) { xf86Msg(X_ERROR, "Bell: cannot open audio device \"%s\": %s\n", AUDIO_DEVICE, strerror(errno)); return; } freq = pitch; freq = min(freq, (BELL_RATE / 2) - 1); freq = max(freq, 2 * BELL_HZ); /* * Ensure full waves per buffer */ freq -= freq % BELL_HZ; if (freq != lastFreq) { lastFreq = freq; ampl = 16384.0; cyclen = (double) freq / (double) BELL_RATE; phase = 0.0; for (i = 0; i < BELL_SAMPLES; i++) { samples[i] = (short) (ampl * sin(2.0 * M_PI * phase)); phase += cyclen; if (phase >= 1.0) phase -= 1.0; } } repeats = (duration + (BELL_MS / 2)) / BELL_MS; repeats = max(repeats, BELL_MIN); loudness = max(0, loudness); loudness = min(loudness, 100); #ifdef DEBUG ErrorF("BELL : freq %d volume %d duration %d repeats %d\n", freq, loudness, duration, repeats); #endif AUDIO_INITINFO(&audioInfo); audioInfo.play.encoding = AUDIO_ENCODING_LINEAR; audioInfo.play.sample_rate = BELL_RATE; audioInfo.play.channels = 2; audioInfo.play.precision = 16; audioInfo.play.gain = min(AUDIO_MAX_GAIN, AUDIO_MAX_GAIN * loudness / 100); if (ioctl(audioFD, AUDIO_SETINFO, &audioInfo) < 0){ xf86Msg(X_ERROR, "Bell: AUDIO_SETINFO failed on audio device \"%s\": %s\n", AUDIO_DEVICE, strerror(errno)); close(audioFD); return; } iovcnt = 0; for (cnt = 0; cnt <= repeats; cnt++) { if (cnt == repeats) { /* Insert a bit of silence so that multiple beeps are distinct and * not compressed into a single tone. */ iov[iovcnt].iov_base = (char *) silence; iov[iovcnt++].iov_len = sizeof(silence); } else { iov[iovcnt].iov_base = (char *) samples; iov[iovcnt++].iov_len = sizeof(samples); } if ((iovcnt >= IOV_MAX) || (cnt == repeats)) { written = writev(audioFD, iov, iovcnt); if ((written < ((int)(sizeof(samples) * iovcnt)))) { /* audio buffer was full! */ int naptime; if (written == -1) { if (errno != EAGAIN) { xf86Msg(X_ERROR, "Bell: writev failed on audio device \"%s\": %s\n", AUDIO_DEVICE, strerror(errno)); close(audioFD); return; } i = iovcnt; } else { i = ((sizeof(samples) * iovcnt) - written) / sizeof(samples); } cnt -= i; /* sleep a little to allow audio buffer to drain */ naptime = BELL_MS * i; poll(NULL, 0, naptime); i = ((sizeof(samples) * iovcnt) - written) % sizeof(samples); iovcnt = 0; if ((written != -1) && (i > 0)) { iov[iovcnt].iov_base = ((char *) samples) + i; iov[iovcnt++].iov_len = sizeof(samples) - i; } } else { iovcnt = 0; } } } close(audioFD); return; }
static int init(struct options *options) { char **parm = options->driver_parm; audio_info_t ainfo; int gain = 128; int bsize = 32 * 1024; parm_init(parm); chkparm1("gain", gain = strtoul(token, NULL, 0)); chkparm1("buffer", bsize = strtoul(token, NULL, 0)); parm_end(); if ((audio_fd = open("/dev/sound", O_WRONLY)) == -1) return -1; /* try to open audioctldevice */ if ((audioctl_fd = open("/dev/audioctl", O_RDWR)) < 0) { fprintf(stderr, "couldn't open audioctldevice\n"); close(audio_fd); return -1; } /* empty buffers before change config */ ioctl(audio_fd, AUDIO_DRAIN, 0); /* drain everything out */ ioctl(audio_fd, AUDIO_FLUSH); /* flush audio */ ioctl(audioctl_fd, AUDIO_FLUSH); /* flush audioctl */ /* get audio parameters. */ if (ioctl(audioctl_fd, AUDIO_GETINFO, &ainfo) < 0) { fprintf(stderr, "AUDIO_GETINFO failed!\n"); close(audio_fd); close(audioctl_fd); return -1; } close(audioctl_fd); if (gain < AUDIO_MIN_GAIN) gain = AUDIO_MIN_GAIN; if (gain > AUDIO_MAX_GAIN) gain = AUDIO_MAX_GAIN; AUDIO_INITINFO(&ainfo); ainfo.play.sample_rate = options->rate; ainfo.play.channels = options->format & XMP_FORMAT_MONO ? 1 : 2; if (options->format & XMP_FORMAT_8BIT) { ainfo.play.precision = 8; ainfo.play.precision = AUDIO_ENCODING_ULINEAR; options->format |= XMP_FORMAT_UNSIGNED; } else { ainfo.play.precision = 16; ainfo.play.precision = AUDIO_ENCODING_SLINEAR; options->format &= ~XMP_FORMAT_UNSIGNED; } ainfo.play.gain = gain; ainfo.play.buffer_size = bsize; if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo) == -1) { close(audio_fd); return -1; } return 0; }
FILE *out_file_open(char *outFile, int *wav_format, int rate, int mapping_family, int *channels) { FILE *fout=NULL; /*Open output file*/ if (strlen(outFile)==0) { #if defined HAVE_SYS_SOUNDCARD_H int audio_fd, format, stereo; audio_fd=open("/dev/dsp", O_WRONLY); if (audio_fd<0) { perror("Cannot open /dev/dsp"); quit(1); } format=AFMT_S16_NE; if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1) { perror("SNDCTL_DSP_SETFMT"); close(audio_fd); quit(1); } stereo=0; if (*channels==2) stereo=1; if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1) { perror("SNDCTL_DSP_STEREO"); close(audio_fd); quit(1); } if (stereo!=0) { if (*channels==1) fprintf (stderr, "Cannot set mono mode, will decode in stereo\n"); *channels=2; } if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate)==-1) { perror("SNDCTL_DSP_SPEED"); close(audio_fd); quit(1); } fout = fdopen(audio_fd, "w"); if(!fout) { perror("Cannot open output"); quit(1); } #elif defined HAVE_LIBSNDIO struct sio_par par; hdl = sio_open(NULL, SIO_PLAY, 0); if (!hdl) { fprintf(stderr, "Cannot open sndio device\n"); quit(1); } sio_initpar(&par); par.sig = 1; par.bits = 16; par.rate = rate; par.pchan = *channels; if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par) || par.sig != 1 || par.bits != 16 || par.rate != rate) { fprintf(stderr, "could not set sndio parameters\n"); quit(1); } *channels = par.pchan; if (!sio_start(hdl)) { fprintf(stderr, "could not start sndio\n"); quit(1); } #elif defined HAVE_SYS_AUDIOIO_H audio_info_t info; int audio_fd; audio_fd = open("/dev/audio", O_WRONLY); if (audio_fd<0) { perror("Cannot open /dev/audio"); quit(1); } AUDIO_INITINFO(&info); #ifdef AUMODE_PLAY /* NetBSD/OpenBSD */ info.mode = AUMODE_PLAY; #endif info.play.encoding = AUDIO_ENCODING_SLINEAR; info.play.precision = 16; info.play.input_sample_rate = rate; info.play.channels = *channels; if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { perror ("AUDIO_SETINFO"); quit(1); } fout = fdopen(audio_fd, "w"); if(!fout) { perror("Cannot open output"); quit(1); } #elif defined WIN32 || defined _WIN32 { unsigned int opus_channels = *channels; if (Set_WIN_Params (INVALID_FILEDESC, rate, SAMPLE_SIZE, opus_channels)) { fprintf (stderr, "Can't access %s\n", "WAVE OUT"); quit(1); } } #else fprintf (stderr, "No soundcard support\n"); quit(1); #endif } else { if (strcmp(outFile,"-")==0) { #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif fout=stdout; } else { fout = fopen_utf8(outFile, "wb"); if (!fout) { perror(outFile); quit(1); } if (*wav_format) { *wav_format = write_wav_header(fout, rate, mapping_family, *channels); if (*wav_format < 0) { fprintf (stderr, "Error writing WAV header.\n"); quit(1); } } } } return fout; }
UINT8 StartStream(UINT8 DeviceID) { UINT32 RetVal; #ifdef USE_LIBAO ao_sample_format ao_fmt; #else #ifdef WIN32 UINT16 Cnt; HANDLE WaveOutThreadHandle; DWORD WaveOutThreadID; //char TestStr[0x80]; #elif defined(__NetBSD__) struct audio_info AudioInfo; #else UINT32 ArgVal; #endif #endif // ! USE_LIBAO if (WaveOutOpen) return 0xD0; // Thread is already active // Init Audio WaveFmt.wFormatTag = WAVE_FORMAT_PCM; WaveFmt.nChannels = 2; WaveFmt.nSamplesPerSec = SampleRate; WaveFmt.wBitsPerSample = 16; WaveFmt.nBlockAlign = WaveFmt.wBitsPerSample * WaveFmt.nChannels / 8; WaveFmt.nAvgBytesPerSec = WaveFmt.nSamplesPerSec * WaveFmt.nBlockAlign; WaveFmt.cbSize = 0; if (DeviceID == 0xFF) return 0x00; #if defined(WIN32) || defined(USE_LIBAO) BUFFERSIZE = SampleRate / 100 * SAMPLESIZE; if (BUFFERSIZE > BUFSIZE_MAX) BUFFERSIZE = BUFSIZE_MAX; #else BUFFERSIZE = 1 << BUFSIZELD; #endif SMPL_P_BUFFER = BUFFERSIZE / SAMPLESIZE; if (AUDIOBUFFERU > AUDIOBUFFERS) AUDIOBUFFERU = AUDIOBUFFERS; PauseThread = true; ThreadPauseConfrm = false; CloseThread = false; StreamPause = false; #ifndef USE_LIBAO #ifdef WIN32 ThreadPauseEnable = true; WaveOutThreadHandle = CreateThread(NULL, 0x00, &WaveOutThread, NULL, 0x00, &WaveOutThreadID); if(WaveOutThreadHandle == NULL) return 0xC8; // CreateThread failed CloseHandle(WaveOutThreadHandle); RetVal = waveOutOpen(&hWaveOut, ((UINT)DeviceID - 1), &WaveFmt, 0x00, 0x00, CALLBACK_NULL); if(RetVal != MMSYSERR_NOERROR) #else ThreadPauseEnable = false; #ifdef __NetBSD__ hWaveOut = open("/dev/audio", O_WRONLY); #else hWaveOut = open("/dev/dsp", O_WRONLY); #endif if (hWaveOut < 0) #endif #else // ifdef USE_LIBAO ao_initialize(); ThreadPauseEnable = false; ao_fmt.bits = WaveFmt.wBitsPerSample; ao_fmt.rate = WaveFmt.nSamplesPerSec; ao_fmt.channels = WaveFmt.nChannels; ao_fmt.byte_format = AO_FMT_NATIVE; ao_fmt.matrix = NULL; dev_ao = ao_open_live(ao_default_driver_id(), &ao_fmt, NULL); if (dev_ao == NULL) #endif { CloseThread = true; return 0xC0; // waveOutOpen failed } WaveOutOpen = true; //sprintf(TestStr, "Buffer 0,0:\t%p\nBuffer 0,1:\t%p\nBuffer 1,0:\t%p\nBuffer 1,1:\t%p\n", // &BufferOut[0][0], &BufferOut[0][1], &BufferOut[1][0], &BufferOut[1][1]); //AfxMessageBox(TestStr); #ifndef USE_LIBAO #ifdef WIN32 for (Cnt = 0x00; Cnt < AUDIOBUFFERU; Cnt ++) { WaveHdrOut[Cnt].lpData = BufferOut[Cnt]; // &BufferOut[Cnt][0x00]; WaveHdrOut[Cnt].dwBufferLength = BUFFERSIZE; WaveHdrOut[Cnt].dwBytesRecorded = 0x00; WaveHdrOut[Cnt].dwUser = 0x00; WaveHdrOut[Cnt].dwFlags = 0x00; WaveHdrOut[Cnt].dwLoops = 0x00; WaveHdrOut[Cnt].lpNext = NULL; WaveHdrOut[Cnt].reserved = 0x00; RetVal = waveOutPrepareHeader(hWaveOut, &WaveHdrOut[Cnt], sizeof(WAVEHDR)); WaveHdrOut[Cnt].dwFlags |= WHDR_DONE; } #elif defined(__NetBSD__) AUDIO_INITINFO(&AudioInfo); AudioInfo.mode = AUMODE_PLAY; AudioInfo.play.sample_rate = WaveFmt.nSamplesPerSec; AudioInfo.play.channels = WaveFmt.nChannels; AudioInfo.play.precision = WaveFmt.wBitsPerSample; AudioInfo.play.encoding = AUDIO_ENCODING_SLINEAR; RetVal = ioctl(hWaveOut, AUDIO_SETINFO, &AudioInfo); if (RetVal) printf("Error setting audio information!\n"); #else ArgVal = (AUDIOBUFFERU << 16) | BUFSIZELD; RetVal = ioctl(hWaveOut, SNDCTL_DSP_SETFRAGMENT, &ArgVal); if (RetVal) printf("Error setting Fragment Size!\n"); ArgVal = AFMT_S16_NE; RetVal = ioctl(hWaveOut, SNDCTL_DSP_SETFMT, &ArgVal); if (RetVal) printf("Error setting Format!\n"); ArgVal = WaveFmt.nChannels; RetVal = ioctl(hWaveOut, SNDCTL_DSP_CHANNELS, &ArgVal); if (RetVal) printf("Error setting Channels!\n"); ArgVal = WaveFmt.nSamplesPerSec; RetVal = ioctl(hWaveOut, SNDCTL_DSP_SPEED, &ArgVal); if (RetVal) printf("Error setting Sample Rate!\n"); #endif #endif // USE_LIBAO if (SoundLog) SaveFile(0x00000000, NULL); PauseThread = false; return 0x00; }
/** * Open the specified device and check capability of the opening device. * * @param devstr [in] device string to open * * @return TRUE on success, FALSE on failure. */ static boolean adin_mic_open(char *devstr) { Audio_hdr Dev_hdr, old_hdr; double vol; /* open the device */ if ((afd = open(devstr, O_RDONLY)) == -1) { if (errno == EBUSY) { jlog("Error: adin_sun4: audio device %s is busy\n", devstr); return(FALSE); } else { jlog("Error: adin_sun4: unable to open %s\n",devstr); return(FALSE); } } /* set recording port to microphone */ AUDIO_INITINFO(&ainfo); ainfo.record.port = AUDIO_MICROPHONE; if (ioctl(afd, AUDIO_SETINFO, &ainfo) == -1) { jlog("Error: adin_sun4: failed to set recording port\n"); return(FALSE); } /* set recording parameters */ if (audio_get_record_config(afd, &Dev_hdr) != AUDIO_SUCCESS) { jlog("Error: adin_sun4: failed to get recording config\n"); return(FALSE); } Dev_hdr.sample_rate = srate; Dev_hdr.samples_per_unit = 1; /* ? I don't know this param. ? */ Dev_hdr.bytes_per_unit = 2; Dev_hdr.channels = 1; Dev_hdr.encoding = AUDIO_ENCODING_LINEAR; if (audio_set_record_config(afd, &Dev_hdr) != AUDIO_SUCCESS) { jlog("Error: adin_sun4: failed to set recording config\n"); return(FALSE); } /* set volume */ vol = (float)volume / (float)100; if (audio_set_record_gain(afd, &vol) != AUDIO_SUCCESS) { jlog("Error: adin_sun4: failed to set recording volume\n"); return(FALSE); } /* flush buffer */ if((ioctl(afd , I_FLUSH , FLUSHRW)) == -1) { jlog("Error: adin_sun4: cannot flush input buffer\n"); return(FALSE); } /* setup polling */ pfd.fd = afd; pfd.events = POLLIN; #if 0 /* pause transfer */ if (audio_pause_record(afd) == AUDIO_ERR_NOEFFECT) { jlog("Error: adin_sun4: cannot pause audio\n"); return(FALSE); } #endif return(TRUE); }
// **** Audio card support // Aquire and enabled audio card // return 0 if ok, -1 if failed int HAE_AquireAudioCard(void *context, UINT32 sampleRate, UINT32 channels, UINT32 bits) { int flag; short int count; INT32 error; audio_info_t sunAudioHeader; char* pAudioDev = HAE_GetAudioDevPlay(g_currentDeviceID, 0); flag = 0; g_activeDoubleBuffer = FALSE; g_shutDownDoubleBuffer = TRUE; g_audioFramesToGenerate = HAE_GetMaxSamplePerSlice(); // get number of frames per sample rate slice // we're going to build this many buffers at a time g_synthFramesPerBlock = HAE_SOLARIS_FRAMES_PER_BLOCK; g_audioPeriodSleepTime = HAE_SOLARIS_SOUND_PERIOD; g_bitSize = bits; g_channels = channels; if (bits == 8) { g_audioByteBufferSize = ((INT32)sizeof(char) * g_audioFramesToGenerate); } else { g_audioByteBufferSize = ((INT32)sizeof(short int) * g_audioFramesToGenerate); } g_audioByteBufferSize *= channels; flag = 1; // allocate buffer blocks g_audioBufferBlock = HAE_Allocate(g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK); if (g_audioBufferBlock) { // try to open wave device // $$kk: 12.17.97: need O_NONBLOCK flag to be compatible with windows #ifdef __linux__ g_waveDevice = open(pAudioDev,O_WRONLY); #else g_waveDevice = open(pAudioDev,O_WRONLY|O_NONBLOCK); #endif if (g_waveDevice > 0) { /* set to multiple open */ if (ioctl(g_waveDevice, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) { TRACE1("HAE_AquireAudioCard: %s set to multiple open\n", pAudioDev); } else { ERROR1("HAE_AquireAudioCard: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", pAudioDev); } AUDIO_INITINFO(&sunAudioHeader); // $$kk: 12.17.97: need AUDIO_GETINFO ioctl to get this to work on solaris x86 // add next 1 line error = ioctl(g_waveDevice, AUDIO_GETINFO, &sunAudioHeader); // $$kk: 03.16.98: not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO, // so let's try init'ing again.... AUDIO_INITINFO(&sunAudioHeader); // Set rendering format of the sun device. sunAudioHeader.play.sample_rate = sampleRate; sunAudioHeader.play.precision = bits; sunAudioHeader.play.channels = channels; sunAudioHeader.play.encoding = AUDIO_ENCODING_LINEAR; error = ioctl(g_waveDevice, AUDIO_SETINFO, &sunAudioHeader); if (error == 0) { g_shutDownDoubleBuffer = FALSE; g_activeDoubleBuffer = TRUE; // must enable process, before thread begins /* Spin threads for device service and possibly * stream service. */ // create thread to manage and render audio frames error = HAE_CreateFrameThread(context, PV_AudioWaveOutFrameThread); if (error == 0) { // ok flag = 0; #ifdef USE_RAWDATA_CHECK { char* fname = "javasound_debug_output.pcm"; debugrawfile = HAE_FileOpenForWrite(fname); } #endif } else { flag = 1; g_activeDoubleBuffer = FALSE; } } } } if (flag) { // something failed HAE_ReleaseAudioCard(context); } return flag; }
static int sun_audio_getinfo(audio_info_t *auinfo) { AUDIO_INITINFO(auinfo); return ioctl(audioctl_fd, AUDIO_GETINFO, auinfo); }
struct sio_hdl * _sio_sun_open(const char *str, unsigned int mode, int nbio) { int fd, flags, fullduplex; struct audio_info aui; struct sio_sun_hdl *hdl; struct sio_par par; char path[PATH_MAX]; switch (*str) { case '/': case ':': /* XXX: for backward compat */ str++; break; default: DPRINTF("_sio_sun_open: %s: '/<devnum>' expected\n", str); return NULL; } hdl = malloc(sizeof(struct sio_sun_hdl)); if (hdl == NULL) return NULL; _sio_create(&hdl->sio, &sio_sun_ops, mode, nbio); snprintf(path, sizeof(path), "/dev/audio%s", str); if (mode == (SIO_PLAY | SIO_REC)) flags = O_RDWR; else flags = (mode & SIO_PLAY) ? O_WRONLY : O_RDONLY; while ((fd = open(path, flags | O_NONBLOCK)) < 0) { if (errno == EINTR) continue; DPERROR(path); goto bad_free; } if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { DPERROR("FD_CLOEXEC"); goto bad_close; } /* * pause the device */ AUDIO_INITINFO(&aui); if (mode & SIO_PLAY) aui.play.pause = 1; if (mode & SIO_REC) aui.record.pause = 1; if (ioctl(fd, AUDIO_SETINFO, &aui) < 0) { DPERROR("sio_open_sun: setinfo"); goto bad_close; } /* * If both play and record are requested then * set full duplex mode. */ if (mode == (SIO_PLAY | SIO_REC)) { fullduplex = 1; if (ioctl(fd, AUDIO_SETFD, &fullduplex) < 0) { DPRINTF("sio_open_sun: %s: can't set full-duplex\n", path); goto bad_close; } } hdl->fd = fd; /* * Default parameters may not be compatible with libsndio (eg. mulaw * encodings, different playback and recording parameters, etc...), so * set parameters to a random value. If the requested parameters are * not supported by the device, then sio_setpar() will pick supported * ones. */ sio_initpar(&par); par.rate = 48000; par.le = SIO_LE_NATIVE; par.sig = 1; par.bits = 16; par.appbufsz = 1200; if (!sio_setpar(&hdl->sio, &par)) goto bad_close; return (struct sio_hdl *)hdl; bad_close: while (close(fd) < 0 && errno == EINTR) ; /* retry */ bad_free: free(hdl); return NULL; }
static int open_output(void) { int include_enc = 0, exclude_enc = PE_BYTESWAP; struct stat sb; audio_info_t auinfo; char *audio_dev, *audio_ctl_dev, *tmp_audio; /* See if the AUDIODEV environment variable is defined, and set the audio device accordingly - Lalit Chhabra 23/Oct/2001 */ if((audio_dev = getenv("AUDIODEV")) != NULL) { dpm.id_name = safe_malloc(strlen(audio_dev)); dpm.name = safe_malloc(strlen(audio_dev)); strcpy(dpm.name, audio_dev); strcpy(dpm.id_name, audio_dev); tmp_audio = safe_malloc(strlen(audio_dev) + 3); audio_ctl_dev = safe_malloc(strlen(audio_dev) + 3); strcpy(tmp_audio, audio_dev); strcpy(audio_ctl_dev, strcat(tmp_audio, "ctl")); } else { audio_ctl_dev = safe_malloc(strlen(AUDIO_CTLDEV) + 3); strcpy(audio_ctl_dev, AUDIO_CTLDEV); } output_counter = play_samples_offset = 0; /* Open the audio device */ if((audioctl_fd = open(audio_ctl_dev, O_RDWR)) < 0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", audio_ctl_dev, strerror(errno)); return -1; } /* ############## */ #if 0 if((dpm.fd = open(dpm.name, O_WRONLY | O_NDELAY)) == -1) { ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); if(errno == EBUSY) { if((dpm.fd = open(dpm.name, O_WRONLY)) == -1) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); close_output(); return -1; } } } #endif if((dpm.fd = open(dpm.name, O_WRONLY)) == -1) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); close_output(); return -1; } if(stat(dpm.name, &sb) < 0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); close_output(); return -1; } if(!S_ISCHR(sb.st_mode)) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Not a audio device", dpm.name); close_output(); return -1; } if(sun_audio_getinfo(&auinfo) < 0) { /* from Francesco Zanichelli's */ /* If it doesn't give info, it probably won't take requests either. Assume it's an old device that does 8kHz uLaw only. Disclaimer: I don't know squat about the various Sun audio devices, so if this is not what we should do, I'll gladly accept modifications. */ ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Cannot inquire %s", dpm.name); include_enc = PE_ULAW|PE_ALAW|PE_MONO; exclude_enc = PE_SIGNED|PE_16BIT|PE_BYTESWAP; dpm.encoding = validate_encoding(dpm.encoding, include_enc, exclude_enc); if(dpm.rate != 8000) ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "Sample rate is changed %d to 8000", dpm.rate); dpm.rate = 8000; return 1; } if(!(dpm.encoding & PE_16BIT)) exclude_enc |= PE_SIGNED; /* Always unsigned */ dpm.encoding = validate_encoding(dpm.encoding, include_enc, exclude_enc); AUDIO_INITINFO(&auinfo); auinfo.play.sample_rate = dpm.rate; auinfo.play.channels = (dpm.encoding & PE_MONO) ? 1 : 2; auinfo.play.encoding = sun_audio_encoding(dpm.encoding); auinfo.play.precision = (dpm.encoding & PE_16BIT) ? 16 : 8; if(sun_audio_setinfo(&auinfo) == -1) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "rate=%d, channels=%d, precision=%d, encoding=%s", auinfo.play.sample_rate, auinfo.play.channels, auinfo.play.precision, output_encoding_string(dpm.encoding)); close_output(); return -1; } return 0; }
// Aquire and enabled audio card // return 0 if ok, -1 if failed int HAE_AquireAudioCapture(void *context, UINT32 encoding, UINT32 sampleRate, UINT32 channels, UINT32 bits, UINT32 audioFramesPerBuffer, UINT_PTR *pCaptureHandle) { audio_info_t sunAudioHeader; INT32 error = -1; char* pAudioDev = HAE_GetAudioDevRec(g_soundDeviceIndex, 0); INT32 minFramesPerBuffer; //fprintf(stderr, "Entering HAE_AquireAudioCapture(encoding=%d, samplerate=%d, channels=%d, bits=%d, framesPerBuffer=%d)\n", // encoding, sampleRate, channels, bits, audioFramesPerBuffer); g_encoding = encoding; g_bitSize = bits; g_channels = channels; g_sampleRate = sampleRate; if( audioFramesPerBuffer == 0 ) { audioFramesPerBuffer = sampleRate * HAE_SOLARIS_DEFAULT_BUFFERSIZE_IN_MS / 1000; } g_audioFramesToRead = audioFramesPerBuffer / g_audioCaptureBufferSizeDivisor; if (pCaptureHandle) { *pCaptureHandle = 0L; } // try to open wave device for recording // $$kk: 12.17.97: need O_NONBLOCK flag to be compatible with windows // $$kk: 10.13.98: we want O_NONBLOCK so that we return failure immediately if the // device is busy (or absent or whatever) rather than blocking. however, i think that // this same O_NONBLOCK flag dictates whether the read() calls should block. even // without the O_NONBLOCK flag set, read() does *not* block for me, so i'm keeping // the flag for now.... g_captureSound = open(pAudioDev,O_RDONLY|O_NONBLOCK); if (g_captureSound > 0) { /* set to multiple open */ if (ioctl(g_captureSound, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) { TRACE1("HAE_AquireAudioCapture: %s set to multiple open\n", pAudioDev); } else { ERROR1("HAE_AquireAudioCapture: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", pAudioDev); } AUDIO_INITINFO(&sunAudioHeader); // Set capture format of the sun device. sunAudioHeader.record.sample_rate = sampleRate; sunAudioHeader.record.precision = bits; sunAudioHeader.record.channels = channels; sunAudioHeader.record.buffer_size = g_audioFramesToRead * channels * bits / 8; sunAudioHeader.record.encoding = AUDIO_ENCODING_LINEAR; if (g_encoding == ULAW) { sunAudioHeader.record.encoding = AUDIO_ENCODING_ULAW; } else if (g_encoding == ALAW) { sunAudioHeader.record.encoding = AUDIO_ENCODING_ALAW; } // start out paused so we don't overflow the device driver buffers sunAudioHeader.record.pause = 1; error = ioctl(g_captureSound, AUDIO_SETINFO, &sunAudioHeader); if (error != -1) { // flush anything we might have accumulated in the capture queue before pausing error = ioctl(g_captureSound, I_FLUSH, FLUSHR); error = ioctl(g_captureSound, AUDIO_GETINFO, &sunAudioHeader); g_audioFramesToRead = sunAudioHeader.record.buffer_size / (channels * bits / 8); if (error != -1) { if (pCaptureHandle) { *pCaptureHandle = (UINT_PTR)g_captureSound; } } } } if (error == -1) { // something failed HAE_ReleaseAudioCapture(context); } //fprintf(stderr, "<< HAE_API_SolarisOS_Capture: HAE_AquireAudioCapture() returning %d\n", error); return error; }
static BOOL Sun_Init(void) { int play_stereo, play_rate; #ifdef SUNOS4 int audiotype; #else audio_device_t audiotype; #endif struct audio_info audioinfo; if (getenv("AUDIODEV")) sndfd = open(getenv("AUDIODEV"), O_WRONLY); else { sndfd = open(SOUNDDEVICE, O_WRONLY); #if defined __NetBSD__ || defined __OpenBSD__ if (sndfd < 0) sndfd = open(SOUNDDEVICE "0", O_WRONLY); #endif } if (sndfd < 0) { _mm_errno = MMERR_OPENING_AUDIO; return 1; } if (!(audiobuffer = (SBYTE *)_mm_malloc(fragsize))) return 1; play_precision = (md_mode & DMODE_16BITS) ? 16 : 8; play_stereo = (md_mode & DMODE_STEREO) ? 2 : 1; play_rate = md_mixfreq; /* attempt to guess the encoding */ play_encoding = -1; if (ioctl(sndfd, AUDIO_GETDEV, &audiotype) < 0) { #ifdef MIKMOD_DEBUG fputs("\rSun driver warning: could not determine audio device type\n", stderr); #endif } else { #if defined SUNOS4 /* SunOS 4 */ switch (audiotype) { case AUDIO_DEV_AMD: /* AMD 79C30 */ /* 8bit mono ulaw 8kHz */ play_rate = md_mixfreq = 8000; md_mode &= ~(DMODE_STEREO | DMODE_16BITS); play_precision = 8; play_stereo = 1; play_encoding = AUDIO_ENCODING_ULAW; break; case AUDIO_DEV_SPEAKERBOX: case AUDIO_DEV_CODEC: /* CS 4231 or DBRI or speaker box */ /* 16bit mono/stereo linear 8kHz - 48kHz */ if (play_precision == 16) play_encoding = AUDIO_ENCODING_LINEAR; /* 8bit mono ulaw 8kHz - 48kHz */ else if (play_precision == 8) { md_mode &= ~(DMODE_STEREO); play_stereo = 1; play_encoding = AUDIO_ENCODING_ULAW; } else { _mm_errno = MMERR_SUN_INIT; return 1; } break; } #elif defined SOLARIS /* Solaris */ if (!strcmp(audiotype.name, "SUNW,am79c30")) { /* AMD 79C30 */ /* 8bit mono ulaw 8kHz */ play_rate = md_mixfreq = 8000; md_mode &= ~(DMODE_STEREO | DMODE_16BITS); play_precision = 8; play_stereo = 1; play_encoding = AUDIO_ENCODING_ULAW; } else if ((!strcmp(audiotype.name, "SUNW,CS4231")) || (!strcmp(audiotype.name, "SUNW,dbri")) || (!strcmp(audiotype.name, "speakerbox"))) { /* CS 4231 or DBRI or speaker box */ /* 16bit mono/stereo linear 8kHz - 48kHz */ if (play_precision == 16) play_encoding = AUDIO_ENCODING_LINEAR; /* 8bit mono ulaw 8kHz - 48kHz */ else if (play_precision == 8) { md_mode &= ~(DMODE_STEREO); play_stereo = 1; play_encoding = AUDIO_ENCODING_ULAW; } else { _mm_errno = MMERR_SUN_INIT; return 1; } } #else /* NetBSD, OpenBSD */ if (!strcmp(audiotype.name, "amd7930")) { /* AMD 79C30 */ /* 8bit mono ulaw 8kHz */ play_rate = md_mixfreq = 8000; md_mode &= ~(DMODE_STEREO | DMODE_16BITS); play_precision = 8; play_stereo = 1; play_encoding = AUDIO_ENCODING_ULAW; } if ((!strcmp(audiotype.name, "Am78C201")) || (!strcmp(audiotype.name, "UltraSound")) ) { /* Gravis UltraSound, AMD Interwave and compatible cards */ /* 16bit stereo linear 44kHz */ play_rate = md_mixfreq = 44100; md_mode |= (DMODE_STEREO | DMODE_16BITS); play_precision = 16; play_stereo = 2; play_encoding = AUDIO_ENCODING_SLINEAR; } #endif } /* Sound devices which were not handled above don't have specific limitations, so try and guess optimal settings */ if (play_encoding == -1) { if ((play_precision == 8) && (play_stereo == 1) && (play_rate <= 8000)) play_encoding = AUDIO_ENCODING_ULAW; else #ifdef SUNOS4 play_encoding = AUDIO_ENCODING_LINEAR; #else play_encoding = (play_precision == 16) ? AUDIO_ENCODING_SLINEAR : AUDIO_ENCODING_ULINEAR; #endif } /* get current audio settings if we want to keep the playback output port */ if (!port) { AUDIO_INITINFO(&audioinfo); if (ioctl(sndfd, AUDIO_GETINFO, &audioinfo) < 0) { _mm_errno = MMERR_SUN_INIT; return 1; } port = audioinfo.play.port; } AUDIO_INITINFO(&audioinfo); audioinfo.play.precision = play_precision; audioinfo.play.channels = play_stereo; audioinfo.play.sample_rate = play_rate; audioinfo.play.encoding = play_encoding; audioinfo.play.port = port; #if defined __NetBSD__ || defined __OpenBSD__ #if defined AUMODE_PLAY_ALL audioinfo.mode = AUMODE_PLAY | AUMODE_PLAY_ALL; #else audioinfo.mode = AUMODE_PLAY; #endif #endif if (ioctl(sndfd, AUDIO_SETINFO, &audioinfo) < 0) { _mm_errno = MMERR_SUN_INIT; return 1; } /* check if our changes were accepted */ if (ioctl(sndfd, AUDIO_GETINFO, &audioinfo) < 0) { _mm_errno = MMERR_SUN_INIT; return 1; } if ((audioinfo.play.precision != play_precision) || (audioinfo.play.channels != play_stereo) || (normalize(audioinfo.play.encoding) != normalize(play_encoding))) { _mm_errno = MMERR_SUN_INIT; return 1; } if (audioinfo.play.sample_rate != play_rate) { /* Accept a shift inferior to 5% of the expected rate */ int delta = audioinfo.play.sample_rate - play_rate; if (delta < 0) delta = -delta; if (delta * 20 > play_rate) { _mm_errno = MMERR_SUN_INIT; return 1; } /* Align to what the card gave us */ md_mixfreq = audioinfo.play.sample_rate; } return VC_Init(); }
static void solaris_play (int argc, char *argv []) { static short buffer [BUFFER_LEN] ; audio_info_t audio_info ; SNDFILE *sndfile ; SF_INFO sfinfo ; unsigned long delay_time ; long k, start_count, output_count, write_count, read_count ; int audio_fd, error, done ; for (k = 1 ; k < argc ; k++) { printf ("Playing %s\n", argv [k]) ; if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo))) { puts (sf_strerror (NULL)) ; continue ; } ; if (sfinfo.channels < 1 || sfinfo.channels > 2) { printf ("Error : channels = %d.\n", sfinfo.channels) ; continue ; } ; /* open the audio device - write only, non-blocking */ if ((audio_fd = open ("/dev/audio", O_WRONLY | O_NONBLOCK)) < 0) { perror ("open (/dev/audio) failed") ; return ; } ; /* Retrive standard values. */ AUDIO_INITINFO (&audio_info) ; audio_info.play.sample_rate = sfinfo.samplerate ; audio_info.play.channels = sfinfo.channels ; audio_info.play.precision = 16 ; audio_info.play.encoding = AUDIO_ENCODING_LINEAR ; audio_info.play.gain = AUDIO_MAX_GAIN ; audio_info.play.balance = AUDIO_MID_BALANCE ; if ((error = ioctl (audio_fd, AUDIO_SETINFO, &audio_info))) { perror ("ioctl (AUDIO_SETINFO) failed") ; return ; } ; /* Delay time equal to 1/4 of a buffer in microseconds. */ delay_time = (BUFFER_LEN * 1000000) / (audio_info.play.sample_rate * 4) ; done = 0 ; while (! done) { read_count = sf_read_short (sndfile, buffer, BUFFER_LEN) ; if (read_count < BUFFER_LEN) { memset (&(buffer [read_count]), 0, (BUFFER_LEN - read_count) * sizeof (short)) ; /* Tell the main application to terminate. */ done = SF_TRUE ; } ; start_count = 0 ; output_count = BUFFER_LEN * sizeof (short) ; while (output_count > 0) { /* write as much data as possible */ write_count = write (audio_fd, &(buffer [start_count]), output_count) ; if (write_count > 0) { output_count -= write_count ; start_count += write_count ; } else { /* Give the audio output time to catch up. */ usleep (delay_time) ; } ; } ; /* while (outpur_count > 0) */ } ; /* while (! done) */ close (audio_fd) ; } ; return ; } /* solaris_play */
/* ============== SNDDMA_Submit Send sound to device if buffer isn't really the dma buffer =============== */ void SNDDMA_Submit(void){ int samplebytes = dma.samplebits / 8; audio_info_t au_info; int s_pos; int chunk_idx; static int last_chunk_idx = -1; if(!snd_inited) return; if(last_chunk_idx == -1){ if(write(audio_fd, dma.buffer, dma.samples * samplebytes) != dma.samples * samplebytes) Com_Printf("initial write on audio device failed\n"); last_chunk_idx = 0; dma.samplepos = 0; return; } if(ioctl(audio_fd, AUDIO_GETINFO, &au_info) == -1){ Com_Printf("AUDIO_GETINFO failed: %s\n", strerror(errno)); return; } if(au_info.play.error){ /* * underflow? clear the error flag and reset the HW sample counter * and send the whole dma_buffer, to get sound output working again */ DPRINTF("audio data underflow\n"); AUDIO_INITINFO(&au_info); au_info.play.error = 0; au_info.play.samples = 0; ioctl(audio_fd, AUDIO_SETINFO, &au_info); if(write(audio_fd, dma.buffer, dma.samples * samplebytes) != dma.samples * samplebytes) Com_Printf("refill sound driver after underflow failed\n"); last_chunk_idx = 0; dma.samplepos = 0; return; } s_pos = au_info.play.samples * dma.channels; chunk_idx =(s_pos % dma.samples) / dma.submission_chunk; DPRINTF("HW DMA Pos=%u(%u), dma.samplepos=%u, play in=%d, last=%d\n", au_info.play.samples, s_pos, dma.samplepos, chunk_idx, last_chunk_idx); while(chunk_idx != last_chunk_idx){ if(write(audio_fd, dma.buffer + dma.samplepos * samplebytes, dma.submission_chunk * samplebytes) != dma.submission_chunk * samplebytes){ Com_Printf("write error on audio device\n"); } if((dma.samplepos += dma.submission_chunk) >= dma.samples) dma.samplepos = 0; if(++last_chunk_idx >= QSND_NUM_CHUNKS) last_chunk_idx = 0; } }
qboolean SNDDMA_Init ( void ) { if (snd_inited) { printf("Sound already init'd\n"); return 0; } shm = &sn; shm->splitbuffer = 0; audio_fd = open("/dev/audio", O_WRONLY|O_NDELAY); if (audio_fd < 0) { if (errno == EBUSY) { Con_Printf("Audio device is being used by another process\n"); } perror("/dev/audio"); Con_Printf("Could not open /dev/audio\n"); return (0); } if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { perror("/dev/audio"); Con_Printf("Could not communicate with audio device.\n"); close(audio_fd); return 0; } // // set to nonblock // if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) { perror("/dev/audio"); close(audio_fd); return 0; } AUDIO_INITINFO(&info); shm->speed = 11025; // try 16 bit stereo info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.sample_rate = 11025; info.play.channels = 2; info.play.precision = 16; if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.sample_rate = 11025; info.play.channels = 1; info.play.precision = 16; if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { Con_Printf("Incapable sound hardware.\n"); close(audio_fd); return 0; } Con_Printf("16 bit mono sound initialized\n"); shm->samplebits = 16; shm->channels = 1; } else { // 16 bit stereo Con_Printf("16 bit stereo sound initialized\n"); shm->samplebits = 16; shm->channels = 2; } shm->soundalive = true; shm->samples = sizeof(dma_buffer) / (shm->samplebits/8); shm->samplepos = 0; shm->submission_chunk = 1; shm->buffer = (unsigned char *)dma_buffer; snd_inited = 1; return 1; }
/* ================== SNDDMA_Init Try to find a sound device to mix for. Returns false if nothing is found. Returns true and fills in the "dma" structure with information for the mixer. ================== */ qboolean SNDDMA_Init(struct sndinfo * s){ int i; int samples; audio_info_t au_info; if(snd_inited) return 1; snd_inited = 0; si = s; // open /dev/audio if(audio_fd < 0){ audio_fd = open(si->device->string, O_WRONLY); if(audio_fd < 0){ Com_Printf("Could not open %s: %s\n", si->device->string, strerror(errno)); return 0; } } // set sample bits & speed if((int)si->speed->value > 0){ AUDIO_INITINFO(&au_info); au_info.play.precision =(int)si->bits->value; au_info.play.encoding = ( au_info.play.precision == 8 ? AUDIO_ENCODING_LINEAR8 : AUDIO_ENCODING_LINEAR); au_info.play.sample_rate =(int)si->speed->value; au_info.play.channels =(int)sndchannels->value; if(ioctl(audio_fd, AUDIO_SETINFO, &au_info) == -1){ Com_Printf("AUDIO_SETINFO failed: %s\n", strerror(errno)); return 0; } } else { for(i = 0; i < sizeof(tryrates) / sizeof(tryrates[0]); i++){ AUDIO_INITINFO(&au_info); au_info.play.precision =(int)si->bits->value; au_info.play.encoding = ( au_info.play.precision == 8 ? AUDIO_ENCODING_LINEAR8 : AUDIO_ENCODING_LINEAR); au_info.play.sample_rate = tryrates[i]; au_info.play.channels =(int)sndchannels->value; if(ioctl(audio_fd, AUDIO_SETINFO, &au_info) == 0) break; Com_Printf("AUDIO_SETINFO failed: %s\n", strerror(errno)); } if(i >= sizeof(tryrates) / sizeof(tryrates[0])) return 0; } dma.samplebits = au_info.play.precision; dma.channels = au_info.play.channels; dma.speed = au_info.play.sample_rate; /* * submit some sound data every ~ 0.1 seconds, and try to buffer 2*0.1 * seconds in sound driver */ samples = dma.channels * dma.speed / 10; for(i = 0;(1 << i) < samples; i++) ; dma.submission_chunk = 1 <<(i - 1); DPRINTF("channels %d, speed %d, log2(samples) %d, submission chunk %d\n", dma.channels, dma.speed, i - 1, dma.submission_chunk); dma.samples = QSND_NUM_CHUNKS * dma.submission_chunk; dma.buffer = calloc(dma.samples, dma.samplebits / 8); if(dma.buffer == NULL){ Com_Printf("Could not alloc sound buffer\n"); return 0; } AUDIO_INITINFO(&au_info); au_info.play.eof = 0; au_info.play.samples = 0; ioctl(audio_fd, AUDIO_SETINFO, &au_info); dma.samplepos = 0; snd_inited = 1; return 1; }
/* * audio_init - open and initialize audio device * * This code works with SunOS 4.x, Solaris 2.x, and PCM; however, it is * believed generic and applicable to other systems with a minor twid * or two. All it does is open the device, set the buffer size (Solaris * only), preset the gain and set the input port. It assumes that the * codec sample rate (8000 Hz), precision (8 bits), number of channels * (1) and encoding (ITU-T G.711 mu-law companded) have been set by * default. */ int audio_init( const char *dname, /* device name */ int bufsiz, /* buffer size */ int unit /* device unit (0-3) */ ) { #ifdef PCM_STYLE_SOUND # define ACTL_DEV "/dev/mixer%d" char actl_dev[30]; # ifdef HAVE_STRUCT_SND_SIZE struct snd_size s_size; # endif # ifdef AIOGFMT snd_chan_param s_c_p; # endif #endif int fd; int rval; const char *actl = #ifdef PCM_STYLE_SOUND actl_dev #else "/dev/audioctl" #endif ; #ifdef PCM_STYLE_SOUND snprintf(actl_dev, sizeof(actl_dev), ACTL_DEV, unit); audio_config_read(unit, &actl, &dname); /* If we have values for cf_c_dev or cf_i_dev, use them. */ if (*cf_c_dev) actl = cf_c_dev; if (*cf_i_dev) dname = cf_i_dev; #endif /* * Open audio device */ fd = open(dname, O_RDWR | O_NONBLOCK, 0777); if (fd < 0) { msyslog(LOG_ERR, "audio_init: %s %m", dname); return (fd); } /* * Open audio control device. */ ctl_fd = open(actl, O_RDWR); if (ctl_fd < 0) { msyslog(LOG_ERR, "audio_init: invalid control device <%s>", actl); close(fd); return(ctl_fd); } /* * Set audio device parameters. */ #ifdef PCM_STYLE_SOUND printf("audio_init: <%s> bufsiz %d\n", dname, bufsiz); rval = fd; # ifdef HAVE_STRUCT_SND_SIZE if (ioctl(fd, AIOGSIZE, &s_size) == -1) printf("audio_init: AIOGSIZE: %s\n", strerror(errno)); else printf("audio_init: orig: play_size %d, rec_size %d\n", s_size.play_size, s_size.rec_size); s_size.play_size = s_size.rec_size = bufsiz; printf("audio_init: want: play_size %d, rec_size %d\n", s_size.play_size, s_size.rec_size); if (ioctl(fd, AIOSSIZE, &s_size) == -1) printf("audio_init: AIOSSIZE: %s\n", strerror(errno)); else printf("audio_init: set: play_size %d, rec_size %d\n", s_size.play_size, s_size.rec_size); # endif /* HAVE_STRUCT_SND_SIZE */ # ifdef SNDCTL_DSP_SETFRAGMENT { int tmp = (16 << 16) + 6; /* 16 fragments, each 2^6 bytes */ if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) printf("audio_init: SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); } # endif /* SNDCTL_DSP_SETFRAGMENT */ # ifdef AIOGFMT if (ioctl(fd, AIOGFMT, &s_c_p) == -1) printf("audio_init: AIOGFMT: %s\n", strerror(errno)); else printf("audio_init: play_rate %lu, rec_rate %lu, play_format %#lx, rec_format %#lx\n", s_c_p.play_rate, s_c_p.rec_rate, s_c_p.play_format, s_c_p.rec_format); # endif /* Grab the device and record masks */ if (ioctl(ctl_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) printf("SOUND_MIXER_READ_DEVMASK: %s\n", strerror(errno)); if (ioctl(ctl_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) printf("SOUND_MIXER_READ_RECMASK: %s\n", strerror(errno)); /* validate and set any specified config file stuff */ if (cf_agc[0] != '\0') { int i; /* recmask */ i = mixer_name(cf_agc, recmask); if (i >= 0) agc = MIXER_WRITE(i); else printf("input %s not in recmask %#x\n", cf_agc, recmask); } if (cf_monitor[0] != '\0') { int i; /* devmask */ i = mixer_name(cf_monitor, devmask); if (i >= 0) monitor = MIXER_WRITE(i); else printf("monitor %s not in devmask %#x\n", cf_monitor, devmask); } #else /* not PCM_STYLE_SOUND */ AUDIO_INITINFO(&info); info.play.gain = AUDIO_MAX_GAIN; info.play.port = AUDIO_SPEAKER; # ifdef HAVE_SYS_AUDIOIO_H info.record.buffer_size = bufsiz; # endif /* HAVE_SYS_AUDIOIO_H */ rval = ioctl(ctl_fd, (int)AUDIO_SETINFO, (char *)&info); if (rval < 0) { msyslog(LOG_ERR, "audio: invalid control device parameters"); close(ctl_fd); close(fd); return(rval); } rval = fd; #endif /* not PCM_STYLE_SOUND */ return (rval); }
static gboolean gst_sunaudiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) { GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink); audio_info_t ainfo; int ret; int ports; ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo); if (ret == -1) { GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s", strerror (errno))); return FALSE; } if (spec->width != 16) return FALSE; ports = ainfo.play.port; AUDIO_INITINFO (&ainfo); ainfo.play.sample_rate = spec->rate; ainfo.play.channels = spec->channels; ainfo.play.precision = spec->width; ainfo.play.encoding = AUDIO_ENCODING_LINEAR; ainfo.play.port = ports; /* buffer_time for playback is not implemented in Solaris at the moment, but at some point in the future, it might be */ ainfo.play.buffer_size = gst_util_uint64_scale (spec->rate * spec->bytes_per_sample, spec->buffer_time, GST_SECOND / GST_USECOND); spec->silence_sample[0] = 0; spec->silence_sample[1] = 0; spec->silence_sample[2] = 0; spec->silence_sample[3] = 0; ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo); if (ret == -1) { GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s", strerror (errno))); return FALSE; } /* Now read back the info to find out the actual buffer size and set segtotal */ AUDIO_INITINFO (&ainfo); ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo); if (ret == -1) { GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s", strerror (errno))); return FALSE; } #if 0 /* We don't actually use the buffer_size from the sound device, because * it seems it's just bogus sometimes */ sunaudiosink->segtotal = spec->segtotal = ainfo.play.buffer_size / spec->segsize; #else sunaudiosink->segtotal = spec->segtotal; #endif sunaudiosink->segtotal_samples = spec->segtotal * spec->segsize / spec->bytes_per_sample; sunaudiosink->segs_written = (gint) ainfo.play.eof; sunaudiosink->samples_written = ainfo.play.samples; sunaudiosink->bytes_per_sample = spec->bytes_per_sample; GST_DEBUG_OBJECT (sunaudiosink, "Got device buffer_size of %u", ainfo.play.buffer_size); return TRUE; }
static int setaudio(struct xmp_options *o) { audio_info_t ainfo, ainfo2; int gain; int bsize = 32 * 1024; int port; char *token, **parm; AUDIO_INITINFO(&ainfo); /* try to open audioctl device */ if ((audioctl_fd = open("/dev/audioctl", O_RDWR)) < 0) { fprintf(stderr, "couldn't open audioctl device\n"); close(audio_fd); return -1; } /* sleep(2); -- Really needed? */ /* empty buffers before change config */ ioctl(audio_fd, AUDIO_DRAIN, 0); /* drain everything out */ ioctl(audio_fd, I_FLUSH, FLUSHRW); /* flush everything */ ioctl(audioctl_fd, I_FLUSH, FLUSHRW); /* flush everything */ /* get audio parameters. */ if (ioctl(audioctl_fd, AUDIO_GETINFO, &ainfo) < 0) { fprintf(stderr, "AUDIO_GETINFO failed!\n"); close(audio_fd); close(audioctl_fd); return -1; } close(audioctl_fd); /* KH: Sun Dbri doesn't support 8bits linear. I dont muck with the gain * or the port setting. I hate when a program does that. There is * nothing more frustrating then having a program change your volume * and change from external speakers to the tiny one */ gain = ainfo.play.gain; port = ainfo.play.port; parm_init(); chkparm1("gain", gain = strtoul(token, NULL, 0)); chkparm1("buffer", bsize = strtoul(token, NULL, 0)); chkparm1("port", port = (int)*token) parm_end(); switch (port) { case 'h': port = AUDIO_HEADPHONE; break; case 'l': port = AUDIO_LINE_OUT; break; case 's': port = AUDIO_SPEAKER; } if (gain < AUDIO_MIN_GAIN) gain = AUDIO_MIN_GAIN; if (gain > AUDIO_MAX_GAIN) gain = AUDIO_MAX_GAIN; AUDIO_INITINFO(&ainfo); /* For CS4231 */ AUDIO_INITINFO(&ainfo2); /* For AMD 7930 if needed */ ainfo.play.sample_rate = o->freq; ainfo.play.channels = o->outfmt & XMP_FMT_MONO ? 1 : 2; ainfo.play.precision = o->resol; ainfo.play.encoding = AUDIO_ENCODING_LINEAR; ainfo2.play.gain = ainfo.play.gain = gain; ainfo2.play.port = ainfo.play.port = port; ainfo2.play.buffer_size = ainfo.play.buffer_size = bsize; if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo) == -1) { /* CS4231 initialization Failed, perhaps we have an AMD 7930 */ if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo2) == -1) { close(audio_fd); return XMP_ERR_DINIT; } o->resol = 0; o->freq = 8000; o->outfmt |= XMP_FMT_MONO; drv_solaris.description = "Solaris AMD7930 PCM audio"; } else { drv_solaris.description = "Solaris CS4231 PCM audio"; } return 0; }
// $$kk: 08.12.98 merge: changed this method to do convert to unsigned data if required by audio hardware void PV_AudioWaveOutFrameThread(void* context) { audio_info_t sunAudioHeader; char *pFillBuffer; INT32 count, currentPos, lastPos, sampleFrameSize; UINT32 startTime, stopTime, fillTime; int i; int rc; int bytesWritten; int bytesToWrite; ioctl(g_waveDevice, AUDIO_GETINFO, &sunAudioHeader); // calculate sample size for convertion of bytes to sample frames sampleFrameSize = 1; if (g_bitSize == 16) { sampleFrameSize *= 2; } if (g_channels == 2) { sampleFrameSize *= 2; } lastPos = sunAudioHeader.play.samples - ((g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK * 2) / sampleFrameSize); if (g_audioBufferBlock) { while ( (g_activeDoubleBuffer) && (g_shutDownDoubleBuffer == FALSE) ) { /* put sync count and XMicroseconds into relation */ /* could be improved by using actual device sample count */ g_checkpointMicros = XMicroseconds(); g_checkpointSyncCount = GM_GetSyncTimeStamp(); // Generate HAE_SOLARIS_FRAMES_PER_BLOCK frames of audio pFillBuffer = (char *)g_audioBufferBlock; for (count = 0; count < HAE_SOLARIS_FRAMES_PER_BLOCK; count++) { // Generate one frame audio HAE_BuildMixerSlice(context, pFillBuffer, g_audioByteBufferSize, g_audioFramesToGenerate); pFillBuffer += g_audioByteBufferSize; if (g_shutDownDoubleBuffer) { break; // time to quit } } // $$kk // for some solaris drivers, we must supply unsigned data when rendering 8 bit data if (g_convertUnsigned && (g_bitSize == 8)) { pFillBuffer = (char *)g_audioBufferBlock; for (i = 0; i < (g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK); i++) { *pFillBuffer = (*pFillBuffer >= 0) ? (0x80 | *pFillBuffer) : (0x7F & *pFillBuffer); pFillBuffer++; } } // $$jb: Changing the write() loop to handle cases when the // device is unavailable, or we can't write our entire buffer bytesWritten = 0; bytesToWrite = (g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK); while( bytesToWrite > 0 ) { //$$fb don't write when it's time to quit. if( g_shutDownDoubleBuffer) { break; } rc = write(g_waveDevice, ((char *)g_audioBufferBlock+bytesWritten), (size_t)bytesToWrite); if ( rc > 0 ) { #ifdef USE_RAWDATA_CHECK if (debugrawfile) { HAE_WriteFile(debugrawfile, ((char *)g_audioBufferBlock+bytesWritten), rc); } #endif bytesWritten += rc; bytesToWrite -= rc; } else { // $$jb: This happens when the device buffers cannot // be written to. Make sure we're not shutting down and // sleep a bit so that we don't completely hog the CPU if( g_shutDownDoubleBuffer == FALSE ) { HAE_SleepFrameThread(context, HAE_SOLARIS_SOUND_PERIOD); } else { break; } } } // O.k. We're done for now. // Let the rest of the system know we're done .... ioctl(g_waveDevice, AUDIO_GETINFO, &sunAudioHeader); currentPos = sunAudioHeader.play.samples; // $$jb: We have successfully written all our bytes. // If we encountered a problem while writing, play.error will be 1. // This should be reset. if( sunAudioHeader.play.error != 0 ) { AUDIO_INITINFO(&sunAudioHeader); sunAudioHeader.play.error = 0; ioctl(g_waveDevice, AUDIO_SETINFO, &sunAudioHeader); } // $$kk: 03.21.00: make sure we sleep at least once so that other threads can run. // this is part of the fix for bug #4318062: "MixerSourceLine.drain hangs after // repeated use." //while ((currentPos < lastPos) && (g_shutDownDoubleBuffer == FALSE)) do { HAE_SleepFrameThread(context, HAE_SOLARIS_SOUND_PERIOD); // in ms ioctl(g_waveDevice, AUDIO_GETINFO, &sunAudioHeader); currentPos = sunAudioHeader.play.samples; // $$jb: Removing the bit of code that breaks out // of this timing loop on sunAudioHeader.play.error != 0. } while ((currentPos < lastPos) && (lastPos - currentPos < (1 << 28)) && /* see note A */ (g_shutDownDoubleBuffer == FALSE)); // Note A: $$ay: Additional safeguard for wraparound of sample // ------ count from 1 << 32 - 1. Make sure the difference is // not a huge value lastPos += (g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK) / sampleFrameSize; // ... and reschedule ourselves. } g_activeDoubleBuffer = FALSE; } }
static int BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) { const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); SDL_AudioFormat format = 0; audio_info_t info; /* We don't care what the devname is...we'll try to open anything. */ /* ...but default to first name in the list... */ if (devname == NULL) { devname = SDL_GetAudioDeviceName(0, iscapture); if (devname == NULL) { SDL_SetError("No such audio device"); return 0; } } /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); if (this->hidden == NULL) { SDL_OutOfMemory(); return 0; } SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Open the audio device */ this->hidden->audio_fd = open(devname, flags, 0); if (this->hidden->audio_fd < 0) { SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); return 0; } AUDIO_INITINFO(&info); /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(&this->spec); /* Set to play mode */ info.mode = AUMODE_PLAY; if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) { BSDAUDIO_CloseDevice(this); SDL_SetError("Couldn't put device into play mode"); return 0; } AUDIO_INITINFO(&info); for (format = SDL_FirstAudioFormat(this->spec.format); format; format = SDL_NextAudioFormat()) { switch (format) { case AUDIO_U8: info.play.encoding = AUDIO_ENCODING_ULINEAR; info.play.precision = 8; break; case AUDIO_S8: info.play.encoding = AUDIO_ENCODING_SLINEAR; info.play.precision = 8; break; case AUDIO_S16LSB: info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; info.play.precision = 16; break; case AUDIO_S16MSB: info.play.encoding = AUDIO_ENCODING_SLINEAR_BE; info.play.precision = 16; break; case AUDIO_U16LSB: info.play.encoding = AUDIO_ENCODING_ULINEAR_LE; info.play.precision = 16; break; case AUDIO_U16MSB: info.play.encoding = AUDIO_ENCODING_ULINEAR_BE; info.play.precision = 16; break; default: continue; } if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) { break; } } if (!format) { BSDAUDIO_CloseDevice(this); SDL_SetError("No supported encoding for 0x%x", this->spec.format); return 0; } this->spec.format = format; AUDIO_INITINFO(&info); info.play.channels = this->spec.channels; if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) { this->spec.channels = 1; } AUDIO_INITINFO(&info); info.play.sample_rate = this->spec.freq; info.blocksize = this->spec.size; info.hiwat = 5; info.lowat = 3; (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info); (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info); this->spec.freq = info.play.sample_rate; /* Allocate mixing buffer */ this->hidden->mixlen = this->spec.size; this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); if (this->hidden->mixbuf == NULL) { BSDAUDIO_CloseDevice(this); SDL_OutOfMemory(); return 0; } SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); BSDAUDIO_Status(this); /* We're ready to rock and roll. :-) */ return (0); }
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { struct userdata *u = PA_SINK(o)->userdata; int err; audio_info_t info; switch (code) { case PA_SINK_MESSAGE_GET_LATENCY: { pa_usec_t r = 0; if (u->fd >= 0) { err = ioctl(u->fd, AUDIO_GETINFO, &info); pa_assert(err >= 0); r += pa_bytes_to_usec(u->written_bytes, &PA_SINK(o)->sample_spec); r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &PA_SINK(o)->sample_spec); if (u->memchunk.memblock) r += pa_bytes_to_usec(u->memchunk.length, &PA_SINK(o)->sample_spec); } *((pa_usec_t*) data) = r; return 0; } case PA_SINK_MESSAGE_SET_VOLUME: if (u->fd >= 0) { AUDIO_INITINFO(&info); info.play.gain = pa_cvolume_avg((pa_cvolume*)data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; assert(info.play.gain <= AUDIO_MAX_GAIN); if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) pa_log("AUDIO_SETINFO: Unsupported volume."); else pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); } else { return 0; } } break; case PA_SINK_MESSAGE_GET_VOLUME: if (u->fd >= 0) { err = ioctl(u->fd, AUDIO_GETINFO, &info); assert(err >= 0); pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels, info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); return 0; } break; case PA_SINK_MESSAGE_SET_MUTE: if (u->fd >= 0) { AUDIO_INITINFO(&info); info.output_muted = !!PA_PTR_TO_UINT(data); if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); else return 0; } break; case PA_SINK_MESSAGE_GET_MUTE: if (u->fd >= 0) { err = ioctl(u->fd, AUDIO_GETINFO, &info); pa_assert(err >= 0); *(int*)data = !!info.output_muted; return 0; } break; } return pa_sink_process_msg(o, code, data, offset, chunk); }