Caveats
Creating Modules with Multiple Objects
NeXT's dynamic loading system expects the first object in a bundle to be the "main" object (for Resound, the "main" object is the object in your bundle that subclassed from Module). However, ProjectBuilder.app links the objects in alphabetical order, regardless of what's the "main" object in your bundle. If you have more than one code file in your project, the bundle will not compile properly.
You can fix this by re-linking the bundle yourself. For example, for an FFT module I'm working on, Project builder links my object files together as such:
cc -g -O -Wall -I./sym -arch m68k -nostdlib m68k_obj/DiscreteGraphView.o m68k_obj/FFTController.o m68k_obj/FFTModule.o m68k_obj/FFT.o -r -o FFT.bundle/FFT
This links the DiscreteGraphView code before the FFTModule code, and so the bundle doesn't work. So I re-link the object files by building with a target of Bundle (which builds everything right but the bundle-executable itself), removing the bad bundle-executable, re-linking it the right way, and stripping it manually:
rm FFT.bundle/FFT
cc -g -O -Wall -I./sym -arch m68k -nostdlib m68k_obj/FFTModule.o m68k_obj/DiscreteGraphView.o m68k_obj/FFTController.o m68k_obj/FFT.o -r -o FFT.bundle/FFT
strip -x -u FFT.bundle/FFT
Alternatively, you can control-drag on the Classes list in ProjectBuilder's browser to change the order of the classes. However, ProjectBuilder may occassionally reset these.
About Resound's SoundViews
Resound has made some minor modifications to NeXT's SoundView object to clean up some bugs in the object, add scrolling ability, and add the ruler and amplitude/zero lines. Most of these shouldn't affect your module development at all, but you should be aware that Resound has overridden at least the following SoundView methods:
- initFrame:
- getSelection:size:
- setSelection:size:
- selectAll:
- drawSelf::
Of particular importance are the selection methods. NeXT's Sound Views store selection information as an NXRect of "gray area" over a sound. As a result, it's possible to select far more sound than actually exists! setSelection and getSelection have been modified to accept and return the actual selected values, not NeXT's broken ones. selectAll: selects the entire sound regardless of the current reductionFactor (NeXT's version is also broken here).
Resound's custom Sound View draws its ruler outside the SoundView's valid drawing area (outside the bounds)--just be aware of this--and turns off the SoundView's clipping temporarily while doing so (with [self setClipping:NO]). The ruler is drawn on the Sound View after the Sound View has drawn its sound data. So if you want to scribble on the Sound View, you've been suitably warned.
Replacing the Entire Sound
When replacing the entire sound of a SoundView (through the use of setSound: or some similar method), you should be sure to invalidate the pasteboard if the SoundView is its current owner. Otherwise, the SoundView will become confused when pasting the sound, and the program will bomb (see Pasting above). You can check and invalidate the SoundView using the isOwner: and invalidatePasteboard methods in code like this :
if ([TheModuleController isOwner: mySoundView ])
// mySoundView is the SoundView in question
[TheModuleController invalidatePasteboard];
/* Set the new sound here */
Custom Objects
A number of useful custom widgets have been created throughout Resound's development. Some of these, including good sound meters and real-time sound information tracking objects have been donated with code to the MiscKit. You'll find them under the MiscSoundPalette. The MiscKit is maintained by Don Yacktman (yackd@misckit.com), and all objects in the MiscKit are free for your use in both freeware and professional applications.
Some Suggestions
An important NeXT bug to be aware of: if you set a SoundView's sound with setSound:, the reduction factor (current zoom) is lost. When changing the actual sound associated with a SoundView, you should follow this procedure:
1. Disable the window's flushing
2. Get the current selection information of the SoundView
3. Get the current reduction factor of the SoundView
4. Set the new sound
5. Set the SoundView's reduction factor to #3
6. Set the SoundView's selection information to #2
7. Reenable the window's flush and flush the window.
8. (Remember This!) inform Resound with soundChanged
If you change the rate or number of channels of the sound, this could affect the selection, apparent reduction factor, and scroll position--there are physically more or fewer samples in the sound now, and the scroll position, selection, and reduction factor are all sample-based, so they are often appear to the user to have "changed". This is natural; you can compensate in your module if you like, but just understand that it's not a bug in the underlying application code.
If you compile your module for Intel machines, remember that sound data is normally stored in a different format than Intel machines can directly access. To convert the sound, use the SNDConvertSoundToHost() and SNDConvertHostToSound() functions. Remember to convert the sound back to its native format before finishing.
Remember that the sound data may be fragmented or stereo. This is especially important to keep in mind when traversing the sound information and making changes--fragmented sound isn't all in one array.
Try to operate only on the selection, unless there is no selection. Users tend to wonder why an operation is global even though they selected an area to perform the operation on.
If the sound data is stored in CODEC format, you may need to convert it to and from 16-bit linear using the SNDMuLaw() and SNDiMuLaw() functions.