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: 00:00 | path: /problemcode | permanent link to this entry



    Add a comment to this post:

    Your name:

    Your email: Email me new comments on this post
      (Your email will not be published on this site, and will only be used to contact you directly with a reply to your comment if needed. Oh, and we'll use it to send you new comments on this post it you selected that checkbox.)


    Your website:

    Comments:


    Because of excessive load, this site is generated statically every several hours. Therefore, your comment may take some time to appear here. Unless you get an error message when you click the select button below, then all is normal and the comment will appear in due course.