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
There are no comments on this post which have survived moderation. 67 posts have been culled and 129 blocked. Be the first to make a non-spam comment here, please!