/* * audriver-oss.c * * OSS sound system interface code * * Copyright (c) 2005 Todd MacDermid * Jack Lloyd */ #include #ifdef HAVE_SYS_SOUNDCARD #include #include #include #include #include #include #include #include /* FIXME: this should not be hardcoded, that's just terrible */ #define DEVICE_NAME "/dev/dsp" extern int errno; void * oss_audio_open(cutlass_t *cut_handle, int rate) { cutlass_oss_t *oss_handle; int channels = 1; if((NULL == cut_handle)) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_open: Passed a NULL pointer\n"); return(NULL); } oss_handle = calloc(1, sizeof(cutlass_oss_t)); if (NULL == oss_handle) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_open: Memory allocation failed\n"); return(NULL); } oss_handle->fd = open(DEVICE_NAME, O_RDWR, 0); if(oss_handle->fd < 0) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_open: " "Failed to open %s: %s\n", DEVICE_NAME, strerror(errno)); goto fail; } oss_handle->format = AFMT_S16_NE; if(ioctl(oss_handle->fd, SNDCTL_DSP_SETFMT, &(oss_handle->format)) < 0) { oss_handle->format = AFMT_U8; if(ioctl(oss_handle->fd, SNDCTL_DSP_SETFMT, &(oss_handle->format)) < 0) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_open: " "Failed to set format: %s\n", strerror(errno)); goto fail; } } if(ioctl(oss_handle->fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_open: " "Failed to set channels: %s\n", strerror(errno)); goto fail; } if(channels != 1) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_open: " "Could not set mono mode, and we don't support stereo " "(yet)\n"); goto fail; } oss_handle->rate = rate; if(ioctl(oss_handle->fd, SNDCTL_DSP_SPEED, &(oss_handle->rate)) < 0) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_open: " "Failed to set rate: %s\n", strerror(errno)); goto fail; } return(oss_handle); fail: free(oss_handle); return(NULL); } int oss_audio_capture(cutlass_t *cut_handle, cutlass_oss_t *oss_handle, float *samples, int max_samples) { int16_t local_samples16[CUTLASS_AUDIO_RING_SIZE]; uint8_t local_samples8[CUTLASS_AUDIO_RING_SIZE]; int i; int len; int to_read; if((NULL == cut_handle) || (NULL == oss_handle) || (NULL == samples)) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_capture: Passed a NULL pointer\n"); return(-1); } if(max_samples > CUTLASS_AUDIO_RING_SIZE) { to_read = CUTLASS_AUDIO_RING_SIZE; } else { to_read = max_samples; } switch(oss_handle->format) { case AFMT_S16_NE: len = read(oss_handle->fd, local_samples16, to_read * 2); len = len/2; for(i = 0; (i < len) && (i < max_samples); i++) { samples[i] = local_samples16[i]; /* if(!(i%32)) { printf("cap %d: %f %d\n", i, samples[i], local_samples16[i]); } */ } break; case AFMT_U8: len = read(oss_handle->fd, local_samples8, to_read); for(i = 0; (i < len) && (i < max_samples); i++) { samples[i] = (local_samples8[i] - 128) * 256.0; } break; default: cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_capture: oss_handle has unknown format\n"); return(-1); } if(len < 0) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_capture: Read returned %d bytes: %s\n", len, strerror(errno)); } return(len); } int oss_audio_play(cutlass_t *cut_handle, cutlass_oss_t *oss_handle, float *samples, int num_samples) { int16_t local_samples16[CUTLASS_AUDIO_RING_SIZE]; uint8_t local_samples8[CUTLASS_AUDIO_RING_SIZE]; int i; int len; int num_bytes; if((NULL == cut_handle) || (NULL == oss_handle) || (NULL == samples)) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_play: Passed a NULL pointer\n"); return(-1); } switch(oss_handle->format) { case AFMT_S16_NE: for(i = 0; (i < num_samples) && (i < CUTLASS_AUDIO_RING_SIZE); i++) { local_samples16[i] = samples[i]; } num_bytes = num_samples * 2; len = write(oss_handle->fd, local_samples16, num_bytes); break; case AFMT_U8: for(i = 0; (i < num_samples) && (i < CUTLASS_AUDIO_RING_SIZE); i++) { local_samples8[i] = ((samples[i] / 256) + 128); } num_bytes = num_samples; len = write(oss_handle->fd, local_samples8, num_bytes); break; default: cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_play: oss_handle has unknown format\n"); return(-1); } if(len != num_bytes) { cutlass_sysmsg(cut_handle, CUT_ERROR, "oss_audio_play: Meant to write %d samples, wrote %d\n", num_samples, len); return(-1); } return(0); } int oss_audio_close(cutlass_oss_t *oss_handle) { close(oss_handle->fd); free(oss_handle); return(0); } #else /* no sys/soundcard.h */ #include void * oss_audio_open(cutlass_t *cut_handle, int rate) { return NULL; } int oss_audio_close(cutlass_oss_t *oss_handle) { return 0; } int oss_audio_capture(cutlass_t *cut_handle, cutlass_oss_t *oss_handle, float *samples, int max_samples) { return -1; } int oss_audio_play(cutlass_t *cut_handle, cutlass_oss_t *oss_handle, float *samples, int num_samples) { return -1; } #endif