home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / SoundApps / SNDed / Source / energy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  4.4 KB  |  129 lines

  1. /*------------------------------------------------------------------------------
  2. ENERGY CALCULATION
  3.  
  4. This file contains procedures for computing the energy from a sound file and creating a new
  5.  sound file which is used to display the energy the same way sounds themselves are displayed.
  6.  
  7. Usage: (void) energy("<file>.snd") 
  8. This creates a new sound file "<file>.snd.energy"
  9. ------------------------------------------------------------------------------*/
  10.  
  11. #import <stdio.h>
  12. #import <math.h>
  13. #import <sound/sound.h>
  14. #import "globals.h"
  15.  
  16. /* number of mu-law values over which to compute the energy for a period of 10ms */
  17. #define N (FRAME_SIZE * 3)
  18.  
  19. /* constant used to discriminate between 16-bit linear signal values */
  20. #define DISCRIMINANT   5000
  21.  
  22. /*----------------------------------------------------------------
  23. Take array of original 8 bit coded mu-law signals (originalSound), extract
  24. signal and transform each element to 16 bit linear for calculating the energy
  25. then transform the elements back in 8 bit coded mu-law signal (newSound)
  26. ----------------------------------------------------------------*/
  27. void
  28. soundToEnergyToSound(originalSound,newSound,newSoundSize)
  29. int newSoundSize;
  30. unsigned char 
  31.          *originalSound,/*pointer to contents of original sound file */
  32.          *newSound;/* pointer to contents of new sound file to be created */
  33. {
  34.  int j;
  35.  /* compute average energy for all frames */
  36.  for(j=0;j<newSoundSize;j+=1)
  37.    {
  38.     register double sumEnergy=0;
  39.     {
  40.      /* compute the sum of the energy over three frames for frame number j */
  41.      register int i,supLimit;
  42.      for(i=j*FRAME_SIZE,supLimit=i+N;i<supLimit;++i) 
  43.          sumEnergy+=abs(SNDiMulaw(originalSound[i]));
  44.     }
  45.     {
  46.      register double averageEnergy=sumEnergy/N; /* compute average energy for frame j */
  47.  
  48.      /* multiply the energy by a large constant after having taken the 
  49.      log of it in order that SNDMulaw be able to discriminate the values 
  50.      of the energy for different frames (i.e. different values of j) */
  51.  
  52.      averageEnergy=averageEnergy>1 ? DISCRIMINANT * log10(averageEnergy) : 0;
  53.  
  54.      /* convert energy for frame j back to sound and store it in an array;
  55.      this will be stored in a sound file later */
  56.      {
  57.       unsigned char energyToSound=SNDMulaw(averageEnergy),
  58.                     *mulawArray=newSound+j*FRAME_SIZE;
  59.       int i;
  60.       for(i=0;i<FRAME_SIZE;++i) mulawArray[i]=energyToSound;
  61.      }
  62.     }
  63.    }
  64. }
  65. /* take a string of the form "string.snd" and return a string of the form "string.snd.energy" */
  66. char
  67. *addSuffix(soundFileName)
  68. char *soundFileName;
  69. {
  70.  extern int strlen(); extern char *strcpy(),*strcat();
  71.  int length=strlen(soundFileName);
  72.  char *newName=(char *)malloc((length+8) * sizeof(char));
  73.  if(newName==NULL) {fprintf(stderr,"malloc failed for new name");exit(-1);}
  74.  strcpy(newName,soundFileName);
  75.  newName[length]='\0';
  76.  return (char *) strcat(newName,".energy");
  77. }
  78.  
  79. /*----------------------------------------------------------------
  80. Procedure "energy" takes the name of a .snd file (ex: "forty.snd") as argument
  81. and creates a new file with the suffix .snd.energy (ex: "forty.snd.energy") for
  82. the purpose of displaying the energy the same way as sounds are displayed
  83. ----------------------------------------------------------------*/
  84. void
  85. energy(soundFileName)
  86. char *soundFileName;
  87. {
  88.  SNDSoundStruct *sound;
  89.  
  90.  /* read sound file whose energy is to be computed */
  91.  if(SND_ERR_NONE!=SNDReadSoundfile(soundFileName,&sound))
  92.    {fprintf(stderr,"cannot read file");exit(-1);}
  93.  {
  94.   SNDSoundStruct *newSound;
  95.   {
  96.    /* compute size (in frames) of array which is to hold mu-law values coming from
  97.    the conversion sound-to-energy-to-sound done in procedure soundToEnergyToSound */
  98.    int newSoundSize=sound->dataSize/FRAME_SIZE;
  99.    newSoundSize=newSoundSize>2 ? newSoundSize-2 : 0;
  100.  
  101.    /* allocate storage for new sound structure to be filled by procedure soundToEnergyToSound */
  102.    if(SND_ERR_NONE !=SNDAlloc(
  103.                             &newSound,
  104.                             newSoundSize*FRAME_SIZE,
  105.                             SND_FORMAT_MULAW_8,
  106.                             SND_RATE_CODEC,
  107.                             1,
  108.                             0))
  109.      {fprintf(stderr,"cannot allocate storage for new sound structure");exit(-1);}
  110.     
  111.    soundToEnergyToSound(
  112.                     (unsigned char *)((int)sound + sound->dataLocation),
  113.                     (unsigned char *)((int)newSound + newSound->dataLocation),
  114.                     newSoundSize);
  115.   }
  116.   {
  117.    char *suffixAddedFileName=addSuffix(soundFileName);
  118.  
  119.    /* write newSound stucture (representing the display
  120.    pattern of the energy) to file suffixAddedFile */
  121.  
  122.    SNDWriteSoundfile(suffixAddedFileName,newSound);
  123.    free(suffixAddedFileName);
  124.   }
  125.   SNDFree(sound); SNDFree(newSound);
  126.  }
  127. }
  128.  
  129.