stillhq.com : Mikal, a geek from Canberra living in Silicon Valley (no blather posts) http://www.stillhq.com The life, times, travel and software of Michael Still (no blather posts) en Copyright (c) Michael Still 2000 - 2006 blosxom simplerss20 v20050208hh 180 http://blogs.law.harvard.edu/tech/rss Reading a single byte from stdin with Bash? /problemcode Sun, 08 Sep 2002 07:00:00 GMT I am currently having some pain reading very small amounts of input from stdin with bash. For example I want to be able to just pull the next byte of stdin (as a string). <i>read</i> wants to pull lines. <BR><BR> I did think of doing something like: <pre> cat - > /tmp/foo cat /tmp/foo | cut -b 42 </pre> But the problem with this is that stdin of the bash script I am writing never ends. Perhaps I could so something like: <pre> cat - > /tmp/foo & cat /tmp/foo | cut -b 42 </pre> Then I need to be able to handle the scenario when the reader is ahead of the writing, probably by just spinning until the input appears. <BR><BR> This of course doesn't work as I had expected it to, because the first cat can't be backgrounded because then it looses access to stdin. I need some sort of forking mechanism... <br/><br/> <a href="http://www.stillhq.com/problemcode/000004.commentform.html">Comment</a> http://www.stillhq.com/problemcode/000004.html http://www.stillhq.com/problemcode/000004.html Problems getting OSS to work - The code /problemcode Sun, 31 Mar 2002 06:00:00 GMT It turns out the problem is that I needed to byte swap the audio data from the wav file before playing it. The <a href="/problemcode/source/sound-2.c">fixed code</a> looks like: <BR><BR> <PRE> // Routines to handle the sound for Vic, the Bug #include <sys/types.h> #include <sys/stat.h> #include <sys/soundcard.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> int slots[100]; unsigned int toInteger(char *in){ unsigned int ret; int i; char *p = ((char *) &ret); for(i = 0; i < 4; i++){ *p++ = in[i]; } return ret; } char *getBytes(int input, size_t number, char *expect){ char *data; int i; ssize_t numRead; if((data = malloc(number + 1)) == NULL){ fprintf(stderr, "Malloc error\n"); exit(0); } if((numRead = read(input, data, number)) < 1){ fprintf(stderr, "Malformed wav file (EOF)\n"); exit(0); } data[numRead] = 0; if(expect != NULL){ for(i = 0; i < numRead; i++) data[i] = tolower(data[i]); if(strcmp(expect, data) != 0){ fprintf(stderr, "Read \""); for(i = 0; i < numRead; i++) fprintf(stderr, "%c", (isprint(data[i])) ? data[i] : '%'); fprintf(stderr, "\", expected \"%s\"\n", expect); } } return data; } void playSound(int slotNumber, char *filename){ slots[slotNumber] = 0; switch(fork()){ case -1: // Parent with failure fprintf(stderr, "Sound play fork error\n"); return; break; case 0: // Child { int soundHandle = -1, fileHandle = -1; int channels = 1; // stereo int format; unsigned int rate = 22050; unsigned int fmtLen; int bytes = 0; long i; char *data, *data2; char *tempPtr; ssize_t numRead; printf("Play sound %s\n", filename); if((fileHandle = open(filename, O_RDONLY)) == -1){ fprintf(stderr, "Could not open the specified wav file: %s\n", filename); exit(0); } // Check the format of the wav file free(getBytes(fileHandle, 4, "riff")); free(getBytes(fileHandle, 4, NULL)); // Length of package free(getBytes(fileHandle, 4, "wave")); free(getBytes(fileHandle, 4, "fmt ")); tempPtr = getBytes(fileHandle, 4, NULL); fmtLen = toInteger(tempPtr); free(tempPtr); free(getBytes(fileHandle, 2, NULL)); // Reserved tempPtr = getBytes(fileHandle, 2, NULL); channels = tempPtr[0] - 1; free(tempPtr); tempPtr = getBytes(fileHandle, 4, NULL); rate = toInteger(tempPtr); free(tempPtr); free(getBytes(fileHandle, 4, NULL)); // Bytes per second tempPtr = getBytes(fileHandle, 2, NULL); bytes = tempPtr[0]; free(tempPtr); free(getBytes(fileHandle, 2, NULL)); // Bits per sample free(getBytes(fileHandle, 4, "data")); free(getBytes(fileHandle, 3, NULL)); // Length of data // Open the sound interface if((soundHandle = open("/dev/dsp", O_WRONLY)) == -1){ fprintf(stderr, "Couldn't open the sound device\n"); exit(0); } if(ioctl(soundHandle, SNDCTL_DSP_STEREO, &channels) == -1){ fprintf(stderr, "Could not set stereo\n"); exit(0); } else{ printf("\nStereo set to %d\n", channels); } switch(bytes){ case 1: format = AFMT_U8; break; case 2: if(channels == 0) format = AFMT_S16_LE; else format = AFMT_U8; break; case 4: fprintf(stdout, "Stereo wav file\n"); format = AFMT_S16_LE; break; default: fprintf(stderr, "Unknown byte rate for sound\n"); exit(0); } if(ioctl(soundHandle, SNDCTL_DSP_SETFMT, &format) == -1){ fprintf(stderr, "Could not set format\n"); exit(0); } else{ printf("Format set to %d\n", format); } if(ioctl(soundHandle, SNDCTL_DSP_SPEED, &rate) == -1){ fprintf(stderr, "Could not set rate\n"); exit(0); } else{ printf("Speed set to %d\n", rate); } fprintf(stdout, "Playing file %s: channels = %d, rate = %d, bytes = %d\n", filename, channels, rate, bytes); if((data2 = malloc(1024)) == NULL){ fprintf(stderr, "Memory allocation error\n"); exit(0); } while(1){ if((numRead = read(fileHandle, data, 1024)) == 0) break; for(i = 0; i < numRead; i+=2){ data2[i] = data[i+1]; data2[i+1] = data[i]; } if(write(soundHandle, data2, numRead) == -1){ fprintf(stderr, "Error writing to the sound device\n"); exit(0); } } // Get here when done? close(fileHandle); close(soundHandle); free(data); exit(0); } break; default: return; break; } } </PRE> <br/><br/> <a href="http://www.stillhq.com/problemcode/000003.commentform.html">Comment</a> http://www.stillhq.com/problemcode/000003.html http://www.stillhq.com/problemcode/000003.html Problems getting OSS to work - The code /problemcode Fri, 29 Mar 2002 04:00:00 GMT <a href="/problemcode/source/sound-1.c">The code which doesn't work</a> looks something like this: <BR><BR> <PRE> // Routines to handle the sound for Vic, the Bug #include <sys/types.h> #include <sys/stat.h> #include <sys/soundcard.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> int slots[100]; unsigned int toInteger(char *in){ unsigned int ret; int i; char *p = ((char *) &ret); for(i = 0; i < 4; i++){ *p++ = in[i]; } return ret; } char *getBytes(int input, size_t number, char *expect){ char *data; int i; ssize_t numRead; if((data = malloc(number + 1)) == NULL){ fprintf(stderr, "Malloc error\n"); exit(0); } if((numRead = read(input, data, number)) < 1){ fprintf(stderr, "Malformed wav file (EOF)\n"); exit(0); } data[numRead] = 0; fprintf(stdout, "[%d] ", numRead); fflush(stdout); if(expect != NULL){ for(i = 0; i < numRead; i++) data[i] = tolower(data[i]); if(strcmp(expect, data) != 0){ fprintf(stderr, "Read \""); for(i = 0; i < numRead; i++) fprintf(stderr, "%c", (isprint(data[i])) ? data[i] : '%'); fprintf(stderr, "\", expected \"%s\"\n", expect); } } return data; } void playSound(int slotNumber, char *filename){ slots[slotNumber] = 0; switch(fork()){ case -1: // Parent with failure fprintf(stderr, "Sound play fork error\n"); return; break; case 0: // Child { int soundHandle = -1, fileHandle = -1; int channels = 1; // stereo int format; unsigned int rate = 22050; unsigned int fmtLen; int bytes = 0; long i; char *data; char *tempPtr; ssize_t numRead; if((fileHandle = open(filename, O_RDONLY)) == -1){ fprintf(stderr, "Could not open the specified wav file: %s\n", filename); exit(0); } // Check the format of the wav file free(getBytes(fileHandle, 4, "riff")); free(getBytes(fileHandle, 4, NULL)); // Length of package free(getBytes(fileHandle, 4, "wave")); free(getBytes(fileHandle, 4, "fmt ")); tempPtr = getBytes(fileHandle, 4, NULL); fmtLen = toInteger(tempPtr); free(tempPtr); free(getBytes(fileHandle, 2, NULL)); // Reserved tempPtr = getBytes(fileHandle, 2, NULL); channels = tempPtr[0] - 1; free(tempPtr); tempPtr = getBytes(fileHandle, 4, NULL); rate = toInteger(tempPtr); free(tempPtr); free(getBytes(fileHandle, 4, NULL)); // Bytes per second tempPtr = getBytes(fileHandle, 2, NULL); bytes = tempPtr[0]; free(tempPtr); free(getBytes(fileHandle, 2, NULL)); // Bits per sample free(getBytes(fileHandle, 4, "data")); free(getBytes(fileHandle, 3, NULL)); // Length of data // Open the sound interface if((soundHandle = open("/dev/dsp", O_WRONLY)) == -1){ fprintf(stderr, "Couldn't open the sound device\n"); exit(0); } if(ioctl(soundHandle, SNDCTL_DSP_STEREO, &channels) == -1){ fprintf(stderr, "Could not set stereo\n"); exit(0); } switch(bytes){ case 1: format = AFMT_U8; break; case 2: if(channels == 0) format = AFMT_S16_LE; else format = AFMT_U8; break; case 4: fprintf(stdout, "Stereo wav file\n"); format = AFMT_S16_LE; break; default: fprintf(stderr, "Unknown byte rate for sound\n"); exit(0); } if(ioctl(soundHandle, SNDCTL_DSP_SETFMT, &format) == -1){ fprintf(stderr, "Could not set format\n"); exit(0); } if(ioctl(soundHandle, SNDCTL_DSP_SPEED, &rate) == -1){ fprintf(stderr, "Could not set rate\n"); exit(0); } fprintf(stdout, "Playing file %s: channels = %d, rate = %d, bytes = %d\n", filename, channels, rate, bytes); while(1){ if((numRead = read(fileHandle, data, 1024)) == 0) break; fprintf(stdout, "[%d] ", numRead); fflush(stdout); if(write(soundHandle, data, numRead) == -1){ fprintf(stderr, "Error writing to the sound device\n"); exit(0); } if(ioctl(soundHandle, SNDCTL_DSP_SYNC) == -1){ fprintf(stderr, "Could not sync sound data\n"); exit(0); } // free(data); } // Get here when done? close(fileHandle); close(soundHandle); free(data); exit(0); } break; default: return; break; } } </PRE> <br/><br/> <a href="http://www.stillhq.com/problemcode/000001.commentform.html">Comment</a> http://www.stillhq.com/problemcode/000001.html http://www.stillhq.com/problemcode/000001.html Problems getting OSS to work - The problem /problemcode Fri, 29 Mar 2002 04:00:00 GMT The following code works just fine with 8KHz mono sound, but has troubles with stereo 44KHz sound. The stereo wav files just come out as loud clicking noises. I imagine this is something simple with my IOCTL setup, but I can't see it... <br/><br/> <a href="http://www.stillhq.com/problemcode/000002.commentform.html">Comment</a> http://www.stillhq.com/problemcode/000002.html http://www.stillhq.com/problemcode/000002.html