> I'm new to OSS Programming, and I'm attempting to play some 8bit wav files. > However OSS is telling me that my sound card will not play 8bit , only > 16bit. > If I force it. The sound changes pitch, and is very fast. ( obviously ). > > Is there anyway to convert 8bit to 16bit on the fly? I've noticed that XMMS > also fails to play the 8bit wav file correctly. > > I've even tryed to convert the file from 8bit to 16bit using SOX. But with > the > same results. I would like to support 8bit file wavs in my program as MOST of > > the wavs available are in 8bit format... > > Any one Have some pointers? > > PS: The command I used with sox is " sox -V -r 11025 -w -c 1 backup.wav > temp.wav "
try out also self generated sines write to /dev/dsp hope following example helps /* http://205.159.169.11/reference/dsp/prog_dsp.htm Advanced Sound Programming This section describes some miscellaneous sound programming issues that require special consideration or are less commonly used. We saw earlier that /dev/dsp operates using unsigned data, either 8 or 16 bits in size, while /dev/audio uses mu-law encoded data. It is possible to change the data formats a device uses with the SOUND_PCM_SETFMT ioctl call. A number of data formats are defined in the soundcard.h header file, all prefixed with the string AFMT_. For example, to set the coding format to mu-law, you could use: fmt = AFMT_MU_LAW; ioctl(fd, SOUND_PCM_SETFMT, &fmt); The argument will be returned with the coding format that was selected by the kernel (which will be the same as the one selected unless the device does not support it). The special format AFMT_QUERY will return default format for the device. To find out all of the formats that a given device supports, you can use the SOUND_PCM_GETFMTS ioctl. It returns a bitmask that has bits set for each of the supported formats. The SNDCTL_DSP_GETBLKSIZE ioctl returns the block size that the sound driver uses for data transfers. The returned value is an integer, indicating the number in bytes. This information can be useful in an application program for selecting a buffer size that ensures that the data passed to the driver is transferred in complete blocks. The SNDCTL_DSP_GETCAPS ioctl returns a bitmask identifying various capabilities of a sound card DSP device. They are listed in soundcard.h with labels prefixed by DSP_CAP. A typical capability is DSP_CAP_DUPLEX, a boolean flag indicating whether the device supports full duplex mode (simultaneous record and playback). Example 14-6 illustrates these system calls, displaying information about a DSP device (/dev/dsp by default).Determining DSP Capabilities */ /* * dsp_info.c * Example program to display sound device capabilities */ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/ioctl.h> #include <fcntl.h> #include <linux/soundcard.h> /* utility function for displaying boolean status */ static char *yes_no(int condition) { if (condition) return "yes"; else return "no"; } /* * Set sound device parameters to given values. Return -1 if * values not valid. Sampling rate is returned. */ static int set_dsp_params(int fd, int channels, int bits, int *rate) { int status, val = channels; status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &val); if (status == -1) perror("SOUND_PCM_WRITE_CHANNELS ioctl failed"); if (val != channels) /* not valid, so return */ return -1; val = bits; status = ioctl(fd, SOUND_PCM_WRITE_BITS, &val); if (status == -1) perror("SOUND_PCM_WRITE_BITS ioctl failed"); if (val != bits) return -1; status = ioctl(fd, SOUND_PCM_WRITE_RATE, rate); if (status == -1) perror("SOUND_PCM_WRITE_RATE ioctl failed"); return 0; } int main(int argc, char *argv[]) { int rate; int channels; /* number of channels */ int bits; /* sample size */ int blocksize; /* block size */ int formats; /* data formats */ int caps; /* capabilities */ int deffmt; /* default format */ int min_rate, max_rate; /* min and max sampling rates */ char *device; /* name of device to report on */ int fd; /* file descriptor for device */ int status; /* return value from ioctl */ /* get device name from command line or use default */ if (argc == 2) device = argv[1]; else device = "/dev/dsp"; /* try to open device */ fd = open(device, O_RDWR); if (fd == -1) { fprintf(stderr, "%s: unable to open `%s', ", argv[0], device); perror(""); return 1; } status = ioctl(fd, SOUND_PCM_READ_RATE, &rate); if (status == -1) perror("SOUND_PCM_READ_RATE ioctl failed"); status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &channels); if (status == -1) perror("SOUND_PCM_READ_CHANNELS ioctl failed"); status = ioctl(fd, SOUND_PCM_READ_BITS, &bits); if (status == -1) perror("SOUND_PCM_READ_BITS ioctl failed"); status = ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &blocksize); if (status == -1) perror("SNFCTL_DSP_GETBLKSIZE ioctl failed"); printf( "Information on %s:\n\n" "Defaults:\n" " sampling rate: %d Hz\n" " channels: %d\n" " sample size: %d bits\n" " block size: %d bytes\n", device, rate, channels, bits, blocksize ); /* this requires a more recent version of the sound driver */ // #if SOUND_VERSION >= 301 printf("\nSupported Formats:\n"); deffmt = AFMT_QUERY; status = ioctl(fd, SOUND_PCM_SETFMT, &deffmt); if (status == -1) perror("SOUND_PCM_SETFMT ioctl failed"); status = ioctl(fd, SOUND_PCM_GETFMTS, &formats); if (status == -1) perror("SOUND_PCM_GETFMTS ioctl failed"); if (formats & AFMT_MU_LAW) { printf(" mu-law"); (deffmt == AFMT_MU_LAW) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_A_LAW) { printf(" A-law"); (deffmt == AFMT_A_LAW) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_IMA_ADPCM) { printf(" IMA ADPCM"); (deffmt == AFMT_IMA_ADPCM) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_U8) { printf(" unsigned 8-bit"); (deffmt == AFMT_U8) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_S16_LE) { printf(" signed 16-bit little-endian"); (deffmt == AFMT_S16_LE) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_S16_BE) { printf(" signed 16-bit big-endian"); (deffmt == AFMT_S16_BE) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_S8) { printf(" signed 8-bit"); (deffmt == AFMT_S8) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_U16_LE) { printf(" unsigned 16-bit little-endian"); (deffmt == AFMT_U16_LE) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_U16_BE) { printf(" unsigned 16-bit big-endian"); (deffmt == AFMT_U16_BE) ? printf(" (default)\n") : printf("\n"); } if (formats & AFMT_MPEG) { printf(" MPEG 2"); (deffmt == AFMT_MPEG) ? printf(" (default)\n") : printf("\n"); } printf("\nCapabilities:\n"); status = ioctl(fd, SNDCTL_DSP_GETCAPS, &caps); if (status == -1) perror("SNDCTL_DSP_GETCAPS ioctl failed"); printf( " revision: %d\n" " full duplex: %s\n" " real-time: %s\n" " batch: %s\n" " coprocessor: %s\n" " trigger: %s\n" " mmap: %s\n", caps & DSP_CAP_REVISION, yes_no(caps & DSP_CAP_DUPLEX), yes_no(caps & DSP_CAP_REALTIME), yes_no(caps & DSP_CAP_BATCH), yes_no(caps & DSP_CAP_COPROC), yes_no(caps & DSP_CAP_TRIGGER), yes_no(caps & DSP_CAP_MMAP)); // #endif /* SOUND_VERSION >= 301 */ /* display table heading */ printf( "\nModes and Limits:\n" "Device Sample Minimum Maximum\n" "Channels Size Rate Rate\n" "-------- -------- -------- --------\n" ); /* do mono and stereo */ for (channels = 1; channels <= 2 ; channels++) { /* do 8 and 16 bits */ for (bits = 8; bits <= 16 ; bits += 8) { /* To find the minimum and maximum sampling rates we rely on the fact that the kernel sound driver will round them to the closest legal value. */ min_rate = 1; if (set_dsp_params(fd, channels, bits, &min_rate) == -1) continue; max_rate = 100000; if (set_dsp_params(fd, channels, bits, &max_rate) == -1) continue; /* display the results */ printf("%8d %8d %8d %8d\n", channels, bits, min_rate, max_rate); } } close(fd); return 0; } /* Typical output from the dsp_info program looks like this: Information on /dev/dsp: Defaults: sampling rate: 8000 Hz channels: 1 sample size: 8 bits block size: 4096 bytes Supported Formats: mu-law unsigned 8-bit (default) Capabilities: revision: 1 full duplex: no real-time: no batch: no coprocessor: no trigger: yes mmap: yes Modes and Limits: Device Sample Minimum Maximum Channels Size Rate Rate -------- -------- -------- -------- 1 8 4000 43478 2 8 4000 21739 I mentioned earlier that you can't record and play back at the same time with one sound device. You can, however, change parameters such as sampling rate and sample size "on the fly." First, you need to open the PCM device for read and write. Then, before changing any parameters, use the ioctl call ioctl(fd, SOUND_PCM_SYNC, 0); in order to inform the sound driver that it should complete any data transfers that are in progress. You can now change parameters, or even switch between recording and playback. I used this feature earlier in the parrot example program. You can also stop record or playback immediately using ioctl(fd, SOUND_PCM_RESET, 0). Unfortunately, a true bidirectional mode that allows simultaneous recording and playback is not supported (it likely will be in the future, though). This mode would be useful, for example, for implementing a computerized telephone utility that allows users to communicate using a sound card. There is one other alternative: some sound cards, such as the ProAudioSpectrum, have two independent PCM devices--/dev/dsp and /dev/dsp1. You can use one for read and one for write, resulting in simultaneous recording and playback. In order to perform the simultaneous data transfers, it would probably be best to implement the system as two separate processes. Some applications are time critical. The sound driver transfers data using DMA buffers, a typical buffer size being 64 kilobytes. This can impact real-time applications because of the time needed to fill up buffers for transfer. Transferring 64K of data at 8 kHz would take eight seconds. If a multimedia application was performing an animation, for example, it would be unacceptable to have the display stop for eight seconds while the process was waiting for a full buffer of sound data. You can reduce the buffer size using the ioctl call in this form: ioctl(fd, SOUND_PCM_SUBDIVIDE, &divisor); The divisor parameter takes the value 1, 2, or 4; it reduces the DMA buffer size by the corresponding factor. Note that the divisor operates on the default buffer size, not the current value, so you cannot call the function repeatedly to keep reducing the divisor. For some applications, the smaller DMA buffer size may still not be enough. When the program DOOM was ported to Linux, the performance of the game was impacted by the pauses required to play sound effects. A new real-time ioctl was added to address applications such as this one. The ioctl call is called SNDCTL_DSP_SETFRAGMENT, and is explained in the file experimental.txt included in the kernel sound driver source. */ --- This message contains no viruses. Guaranteed by Kaspersky Anti-Virus. www.antivirus.lv