[comp.sys.next] Trouble with Sound Processing on the NeXT, again !

philwzo@quiche.cs.mcgill.ca (Philippe WIECZOREK) (11/21/90)

	The method (int)convertToFormat:(int)aFormat
			samplingRate:(double)aRate
			channelCount:(int)aChannelCount
	for converting a sound works fine to change the format or the
	sampling rate of a sound, but it seems not to work for changing
	the number of channel of the sound.
	Indeed, I did not manage to convert a stereo channel sound to
	a mono one.
	What is the correct way to do that ?
	Is the fdfilter.c's convertToMono (SNDSoundStruct **) function
	correct ? (the fdfilter.c is located in the directory :
	/NextDeveloper/Examples/DSP/ArrayProcessing/fdfilter )

	Thanx for any reply...


		Phil.


        /============================================================\
       /==============================================================\
      // Philippe WIECZOREK.      | e-mail : philwzo@cs.mcgill.ca     \\
     //  Speech Lab.              | Only NeXT makes it possible        \\
    //   McGill University,       | Please forgive me my english        \\
   //    Montreal PQ. CANADA.     | I am just a little frenchie ! :-)    \\
  /========================================================================\
 /==========================================================================\

laughlin@fornax.UUCP (Bob Laughlin) (11/23/90)

In article <49@homer.cs.mcgill.ca> philwzo@quiche.cs.mcgill.ca (Philippe WIECZOREK) writes:
>
>	The method (int)convertToFormat:(int)aFormat
>			samplingRate:(double)aRate
>			channelCount:(int)aChannelCount
>	for converting a sound works fine to change the format or the
>	sampling rate of a sound, but it seems not to work for changing
>	the number of channel of the sound.
>	Indeed, I did not manage to convert a stereo channel sound to
>	a mono one.
>	What is the correct way to do that ?
>	Is the fdfilter.c's convertToMono (SNDSoundStruct **) function
>	correct ? (the fdfilter.c is located in the directory :
>	/NextDeveloper/Examples/DSP/ArrayProcessing/fdfilter )
>
>	Thanx for any reply...
>
>		Phil.
>
>        /============================================================\
>       /==============================================================\
>      // Philippe WIECZOREK.      | e-mail : philwzo@cs.mcgill.ca     \\
>     //  Speech Lab.              | Only NeXT makes it possible        \\
>    //   McGill University,       | Please forgive me my english        \\
>   //    Montreal PQ. CANADA.     | I am just a little frenchie ! :-)    \\
>  /========================================================================\
> /==========================================================================\


    Neither sndconvert -c 1 nor convertToFormat:samplingRate:channelCount:
are implemented for converting 2 channel to 1, although it will do the
sampling rate conversion and maybe some of the format conversions.
If you examine the error code returned from convertToFormat::: you will
see this. 

    The way that I did it is to allocate a new Sound object
and copy the data over.  Stereo Sound data is stored with alternating
left/right samples (shorts).  I needed to convert stereo sounds 
digitized with Digital Ears to mono and did'nt care which channel I
got.  You'd have to experiment to see whether the even numbered samples
are the left or right channel.

    Below is a method to do this and optionally save the new file to disk.


- convertSoundForAnalysis
//---------------------------------------------------------------------------
//   If the sound file read in is not of the proper format, convert it 
// to the proper format and allow user to save it to a file. For the
// analysis we want 1 channel sound at 44,100 sampling rate and
// 16 bit linear samples.  sampledSound is an instance variable that
// has a valid sound in it when this is called.
//---------------------------------------------------------------------------
{
 id      tempSound = nil ;
 int     i, newDataSize ;
 short   *oldData, *newData ;
 BOOL    needToConvert = NO ;

 if ([sampledSound channelCount] != 1)   {
    NXRunAlertPanel ("", "channelCount is being changed to 1",
                     NULL, NULL, NULL) ; 
    needToConvert = YES ;
 } 
 if ([sampledSound samplingRate] != samplingRate)  {
    NXRunAlertPanel ("", "samplingRate is being converted to %d", 
                     NULL, NULL, NULL, (int) samplingRate) ; 
    needToConvert = YES ;
 } 
 if ([sampledSound dataFormat] != SND_FORMAT_LINEAR_16)  {
    NXRunAlertPanel
           ("", "dataFormat is being converted to SND_FORMAT_LINEAR_16",
            NULL, NULL, NULL) ; 
    needToConvert = YES ;
 } 
 if (needToConvert == NO)
    return self ;

 newDataSize = [sampledSound dataSize] / 2 ;

 tempSound = [Sound new] ;
 [tempSound   setDataSize: newDataSize 
               dataFormat: SND_FORMAT_LINEAR_16
             samplingRate: samplingRate
             channelCount: 1
                 infoSize: 0] ;

 if ([sampledSound needsCompacting])
    [sampledSound compactSamples] ;

 oldData = (short *) [sampledSound data] ;
 newData = (short *) [tempSound data] ;

 // stereo data alternates samples for the left and right channels
 for (i = 0;  i < newDataSize / 2;  ++i, oldData += 2)
     *(newData++) = *oldData ;
     
 [sampledSound free] ;
 sampledSound = tempSound ;

 // see if user wants to save converted sound file
 if (NXRunAlertPanel ("Alert", "Save converted sound to file?",
                      "Yes", "No", NULL) == NX_ALERTDEFAULT)  {
    if (!savePanel) {
       savePanel = [SavePanel new] ;
       [savePanel setPrompt:"Save sound to file"] ;
    }
    // make it easy to save file over the file read in
    if ([savePanel runModalForDirectory: soundDir file: soundFilename])   {
       [NXWait set] ;  NXPing () ;
       if ([sampledSound writeSoundfile:(char *)[savePanel filename]])
          NXRunAlertPanel ("Alert","Save sound file failed", NULL, NULL, NULL);
       [NXArrow set] ;  NXPing () ;
    }
 }
 return self ;
}

-- 
 Bob Laughlin  laughlin@cs.sfu.ca