Content here is by:
Michael Still
mikal@stillhq.com

All my Open Source projects
Extracted view of CVS
Home
Site map

See recent comments. RSS feed of all comments. Raw dump of all comments for research purposes.

ImageMagick book
MythTV book








Sun, 08 Sep 2002



Reading a single byte from stdin with Bash?

    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). read wants to pull lines.

    I did think of doing something like:
    cat - > /tmp/foo
    cat /tmp/foo | cut -b 42
    
    But the problem with this is that stdin of the bash script I am writing never ends. Perhaps I could so something like:
    cat - > /tmp/foo &
    cat /tmp/foo | cut -b 42
    
    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.

    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...

posted at: 07:00 | path: /problemcode | permanent link to this entry


Sun, 31 Mar 2002



Problems getting OSS to work - The code

    It turns out the problem is that I needed to byte swap the audio data from the wav file before playing it. The fixed code looks like:

    // Routines to handle the sound for Vic, the Bug
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    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;
      }
    }
    


posted at: 06:00 | path: /problemcode | permanent link to this entry


Fri, 29 Mar 2002



Problems getting OSS to work - The code

    The code which doesn't work looks something like this:

    // Routines to handle the sound for Vic, the Bug
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    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;
      }
    }
    


posted at: 04:00 | path: /problemcode | permanent link to this entry


Problems getting OSS to work - The problem

    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...

posted at: 04:00 | path: /problemcode | permanent link to this entry