I was surprised how difficult it is to get a linux system that plays sounds in <1MB of flash, so tonight I wrote a 'wavplay' applet.
Cons: - Endian issues? - Probably doesn't follow BB coding standards (I never checked) - Only a single device supported (/dev/dsp) - No mixer Pros: - Only about 500 bytes extra weight on BB to play wavs, (486 cross-compiler). Unfortunately your humble developer has wasted too much time correcting patches for open-source projects only to have them dropped on the floor at the end of it. I may produce a proper patch. If enough people beg. Seriously! Anyhow, this stuff isn't rocket science so you can always do it yourself. regards, Biff. PS: Thanks to the BB devs for a really neat system!
/* * wavplay Busybox applet. * Copyright (c) Bifferos ([email protected]). GPL v2 License. * */ #include <linux/soundcard.h> #include "libbb.h" //usage:#define wavplay_trivial_usage //usage: "WAVFILE" //usage:#define wavplay_full_usage "\n\n" //usage: "Plays a .WAV file\n" typedef struct wav_header { char id[4]; // should always contain "RIFF" int totallength; // total file length minus 8 char wavefmt[8]; // "WAVEfmt " int format; // 16 for PCM short pcm; // 1 for PCM short channels; // # channels int frequency; // frequency int bytes_per_second; short bytes_by_capture; short bits_per_sample; char data[4]; // "data" int bytes_in_data; } wav_header; static void NotWAV(void) { bb_error_msg_and_die("Not a recognised format\n"); } static void ioctl_or_bomb(int fd, int req, int param, const char* msg) { int arg = param; ioctl_or_perror_and_die(fd, req, &arg, msg); } static int read_hdr(int fd_wav, int fd_dsp) { int count; wav_header h; count = read(fd_wav, &h, sizeof(h)); if (count != sizeof(h)) NotWAV(); if (strncmp(h.id, "RIFF", 4)) NotWAV(); if (strncmp(h.wavefmt, "WAVEfmt ", 8)) NotWAV(); if (h.pcm != 1) NotWAV(); if (h.format != 16) NotWAV(); if (strncmp(h.data, "data", 4)) NotWAV(); printf("Channels: %d\n", h.channels); printf("Frequency: %d\n", h.frequency); printf("Bits: %d\n", h.bits_per_sample); ioctl_or_bomb(fd_dsp, SOUND_PCM_WRITE_BITS, h.bits_per_sample, "WRITE_BITS"); ioctl_or_bomb(fd_dsp, SOUND_PCM_WRITE_CHANNELS, h.channels, "WRITE_CHANNELS"); ioctl_or_bomb(fd_dsp, SOUND_PCM_WRITE_RATE, h.frequency, "WRITE_RATE"); return h.bytes_in_data; } static void play(int fd_wav, int fd_dsp) { void* buffer; size_t buffer_len = 0x10000; // 64k buffer. size_t read_result = 1; size_t write_result; buffer = malloc(buffer_len); if (!buffer) bb_error_msg_and_die("malloc"); while(read_result) { read_result = read(fd_wav, buffer, buffer_len); if (read_result == -1) { bb_perror_msg_and_die("Reading WAV"); } write_result = write(fd_dsp, buffer, read_result); if (write_result != read_result) { break; } } } int wavplay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int wavplay_main(int argc, char **argv ) { int wav, dsp; /* wav file and sound device */ unsigned opts; opt_complementary = "=1"; /* must have exactly 1 argument */ opts = getopt32(argv, ""); wav = xopen(argv[argc - 1], O_RDONLY); dsp = xopen("/dev/dsp", O_RDWR); read_hdr(wav, dsp); play(wav, dsp); return 0; }
_______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
