home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / WaveTableObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  36.2 KB  |  1,210 lines  |  [TEXT/KAHL]

  1. /* WaveTableObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "WaveTableObject.h"
  31. #include "Array.h"
  32. #include "WaveTableList.h"
  33. #include "Memory.h"
  34. #include "DataMunging.h"
  35. #include "FixedPoint.h"
  36. #include "WaveTableWindow.h"
  37. #include "WaveTableStorage.h"
  38. #include "BufferedFileInput.h"
  39. #include "BufferedFileOutput.h"
  40. #include "BinaryCodedDecimal.h"
  41.  
  42.  
  43. struct WaveTableObjectRec
  44.     {
  45.         MyBoolean                                DataModified;
  46.  
  47.         char*                                        Name;
  48.         WaveTableStorageRec*        WaveTableData;
  49.         char*                                        WaveTableFormula;
  50.         double                                    TestAttackDuration;
  51.         double                                    TestDecayDuration;
  52.         double                                    TestFrequency;
  53.         long                                        TestSamplingRate;
  54.  
  55.         WaveTableWindowRec*            WaveTableWindow;
  56.  
  57.         struct CodeCenterRec*        CodeCenter;
  58.         struct MainWindowRec*        MainWindow;
  59.         WaveTableListRec*                WaveTableList;
  60.  
  61.         short                                        SavedWindowXLoc;
  62.         short                                        SavedWindowYLoc;
  63.         short                                        SavedWindowWidth;
  64.         short                                        SavedWindowHeight;
  65.     };
  66.  
  67.  
  68. /* create a new wave table object with reasonable defaults. */
  69. WaveTableObjectRec*        NewWaveTableObject(struct CodeCenterRec* CodeCenter,
  70.                                                 struct MainWindowRec* MainWindow,
  71.                                                 struct WaveTableListRec* WaveTableList)
  72.     {
  73.         WaveTableObjectRec*    WaveTableObj;
  74.  
  75.         WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
  76.             "WaveTableObjectRec");
  77.         if (WaveTableObj == NIL)
  78.             {
  79.              FailurePoint1:
  80.                 return NIL;
  81.             }
  82.         WaveTableObj->DataModified = False;
  83.         WaveTableObj->WaveTableWindow = NIL;
  84.         WaveTableObj->CodeCenter = CodeCenter;
  85.         WaveTableObj->MainWindow = MainWindow;
  86.         WaveTableObj->WaveTableList = WaveTableList;
  87.         WaveTableObj->TestAttackDuration = 1;
  88.         WaveTableObj->TestDecayDuration = 2;
  89.         WaveTableObj->TestFrequency = 261.625565300598635;
  90.         WaveTableObj->TestSamplingRate = 22050;
  91.         WaveTableObj->SavedWindowXLoc = 0;
  92.         WaveTableObj->SavedWindowYLoc = 0;
  93.         WaveTableObj->SavedWindowWidth = 0;
  94.         WaveTableObj->SavedWindowHeight = 0;
  95.         WaveTableObj->Name = StringToBlockCopy("untitled");
  96.         if (WaveTableObj->Name == NIL)
  97.             {
  98.              FailurePoint2:
  99.                 ReleasePtr((char*)WaveTableObj);
  100.                 goto FailurePoint1;
  101.             }
  102.         WaveTableObj->WaveTableFormula = StringToBlockCopy(
  103.             "# data : fixedarray; frames : integer; tables : integer\x0a");
  104.         if (WaveTableObj->WaveTableFormula == NIL)
  105.             {
  106.              FailurePoint3:
  107.                 ReleasePtr(WaveTableObj->Name);
  108.                 goto FailurePoint2;
  109.             }
  110.         WaveTableObj->WaveTableData = NewWaveTableStorage(eSample16bit,256);
  111.         if (WaveTableObj->WaveTableData == NIL)
  112.             {
  113.              FailurePoint4:
  114.                 ReleasePtr(WaveTableObj->WaveTableFormula);
  115.                 goto FailurePoint3;
  116.             }
  117.         return WaveTableObj;
  118.     }
  119.  
  120.  
  121. /* create a new wave table based on the data being passed in. */
  122. WaveTableObjectRec*        NewWaveTableObjectFromData(struct CodeCenterRec* CodeCenter,
  123.                                                 struct MainWindowRec* MainWindow,
  124.                                                 struct WaveTableListRec* WaveTableList, char* RawData,
  125.                                                 NumBitsType NumBits, long NumTables, long FramesPerTable)
  126.     {
  127.         long                                Scan;
  128.         WaveTableObjectRec*    WaveTableObj;
  129.  
  130.         WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
  131.             "WaveTableObjectRec");
  132.         if (WaveTableObj == NIL)
  133.             {
  134.              FailurePoint1:
  135.                 return NIL;
  136.             }
  137.         WaveTableObj->DataModified = False;
  138.         WaveTableObj->WaveTableWindow = NIL;
  139.         WaveTableObj->CodeCenter = CodeCenter;
  140.         WaveTableObj->MainWindow = MainWindow;
  141.         WaveTableObj->WaveTableList = WaveTableList;
  142.         WaveTableObj->TestAttackDuration = 1;
  143.         WaveTableObj->TestDecayDuration = 2;
  144.         WaveTableObj->TestFrequency = 261.625565300598635;
  145.         WaveTableObj->TestSamplingRate = 22050;
  146.         WaveTableObj->SavedWindowXLoc = 0;
  147.         WaveTableObj->SavedWindowYLoc = 0;
  148.         WaveTableObj->SavedWindowWidth = 0;
  149.         WaveTableObj->SavedWindowHeight = 0;
  150.         WaveTableObj->Name = StringToBlockCopy("AlgoWaveTable Copy");
  151.         if (WaveTableObj->Name == NIL)
  152.             {
  153.              FailurePoint2:
  154.                 ReleasePtr((char*)WaveTableObj);
  155.                 goto FailurePoint1;
  156.             }
  157.         WaveTableObj->WaveTableFormula = StringToBlockCopy(
  158.             "# data : fixedarray; frames : integer; tables : integer\x0a");
  159.         if (WaveTableObj->WaveTableFormula == NIL)
  160.             {
  161.              FailurePoint3:
  162.                 ReleasePtr(WaveTableObj->Name);
  163.                 goto FailurePoint2;
  164.             }
  165.         WaveTableObj->WaveTableData = NewWaveTableStorage(NumBits,FramesPerTable);
  166.         if (WaveTableObj->WaveTableData == NIL)
  167.             {
  168.              FailurePoint4:
  169.                 ReleasePtr(WaveTableObj->WaveTableFormula);
  170.                 goto FailurePoint3;
  171.             }
  172.         for (Scan = 0; Scan < NumTables; Scan += 1)
  173.             {
  174.                 if (!WaveTableStorageAppendEntry(WaveTableObj->WaveTableData))
  175.                     {
  176.                      FailurePoint5:
  177.                         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  178.                         goto FailurePoint4;
  179.                     }
  180.             }
  181.         for (Scan = 0; Scan < NumTables; Scan += 1)
  182.             {
  183.                 char*                        BaseAddress;
  184.                 long                        Index;
  185.  
  186.                 switch (NumBits)
  187.                     {
  188.                         default:
  189.                             EXECUTE(PRERR(ForceAbort,"NewWaveTableObjectFromData:  bad NumBits"));
  190.                             break;
  191.                         case eSample8bit:
  192.                             for (Index = 0; Index < FramesPerTable; Index += 1)
  193.                                 {
  194.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,
  195.                                         Index,double2largefixed(
  196.                                         ((double)(((signed char*)RawData)[Scan * FramesPerTable + Index]))
  197.                                         / MAX8BIT));
  198.                                 }
  199.                             break;
  200.                         case eSample16bit:
  201.                             for (Index = 0; Index < FramesPerTable; Index += 1)
  202.                                 {
  203.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,
  204.                                         Index,double2largefixed(
  205.                                         ((double)(((signed short*)RawData)[Scan * FramesPerTable + Index]))
  206.                                         / MAX16BIT));
  207.                                 }
  208.                             break;
  209.                     }
  210.             }
  211.         return WaveTableObj;
  212.     }
  213.  
  214.  
  215. /* dispose of a wave table object */
  216. void                                    DisposeWaveTableObject(WaveTableObjectRec* WaveTableObj)
  217.     {
  218.         CheckPtrExistence(WaveTableObj);
  219.         if (WaveTableObj->WaveTableWindow != NIL)
  220.             {
  221.                 DisposeWaveTableWindow(WaveTableObj->WaveTableWindow);
  222.                 ERROR(WaveTableObj->WaveTableWindow != NIL,PRERR(ForceAbort,
  223.                     "DisposeWaveTableObject:  disposed window but it isn't NIL"));
  224.             }
  225.         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  226.         ReleasePtr(WaveTableObj->Name);
  227.         ReleasePtr(WaveTableObj->WaveTableFormula);
  228.         ReleasePtr((char*)WaveTableObj);
  229.     }
  230.  
  231.  
  232. /* find out if wave table object has been modified */
  233. MyBoolean                            HasWaveTableObjectBeenModified(WaveTableObjectRec* WaveTableObj)
  234.     {
  235.         CheckPtrExistence(WaveTableObj);
  236.         if (WaveTableObj->WaveTableWindow != NIL)
  237.             {
  238.                 return WaveTableObj->DataModified
  239.                     || HasWaveTableWindowBeenModified(WaveTableObj->WaveTableWindow);
  240.             }
  241.          else
  242.             {
  243.                 return WaveTableObj->DataModified;
  244.             }
  245.     }
  246.  
  247.  
  248. /* get a copy of the wave table's name */
  249. char*                                    WaveTableObjectGetNameCopy(WaveTableObjectRec* WaveTableObj)
  250.     {
  251.         char*                                NameTemp;
  252.  
  253.         CheckPtrExistence(WaveTableObj);
  254.         if (WaveTableObj->WaveTableWindow != NIL)
  255.             {
  256.                 NameTemp = WaveTableWindowGetNameCopy(WaveTableObj->WaveTableWindow);
  257.             }
  258.          else
  259.             {
  260.                 NameTemp = CopyPtr(WaveTableObj->Name);
  261.             }
  262.         if (NameTemp != NIL)
  263.             {
  264.                 SetTag(NameTemp,"WaveTableNameCopy");
  265.             }
  266.         return NameTemp;
  267.     }
  268.  
  269.  
  270. /* set the wave table's name.  the object becomes the owner of the Name block, */
  271. /* so the caller should not release it. */
  272. void                                    WaveTableObjectNewName(WaveTableObjectRec* WaveTableObj,
  273.                                                 char* Name)
  274.     {
  275.         CheckPtrExistence(WaveTableObj);
  276.         CheckPtrExistence(Name);
  277.         ReleasePtr(WaveTableObj->Name);
  278.         SetTag(Name,"WaveTableName");
  279.         WaveTableObj->Name = Name;
  280.         WaveTableObj->DataModified = True;
  281.         WaveTableListWaveTableNameChanged(WaveTableObj->WaveTableList,WaveTableObj);
  282.     }
  283.  
  284.  
  285. /* get a copy of the formula applied to the wave table. */
  286. char*                                    WaveTableObjectGetFormulaCopy(WaveTableObjectRec* WaveTableObj)
  287.     {
  288.         char*                                TextCopy;
  289.  
  290.         CheckPtrExistence(WaveTableObj);
  291.         if (WaveTableObj->WaveTableWindow != NIL)
  292.             {
  293.                 TextCopy = WaveTableWindowGetFormulaCopy(WaveTableObj->WaveTableWindow);
  294.             }
  295.          else
  296.             {
  297.                 TextCopy = CopyPtr(WaveTableObj->WaveTableFormula);
  298.             }
  299.         if (TextCopy != NIL)
  300.             {
  301.                 SetTag(TextCopy,"WaveTableFormulaCopy");
  302.             }
  303.         return TextCopy;
  304.     }
  305.  
  306.  
  307. /* install a new formula into the wave table.  the object becomes the owner of */
  308. /* the formula, so the caller should not dispose it. */
  309. void                                    WaveTableObjectNewFormula(WaveTableObjectRec* WaveTableObj,
  310.                                                 char* Formula)
  311.     {
  312.         CheckPtrExistence(WaveTableObj);
  313.         CheckPtrExistence(Formula);
  314.         ReleasePtr(WaveTableObj->WaveTableFormula);
  315.         SetTag(Formula,"WaveTableFormula");
  316.         WaveTableObj->WaveTableFormula = Formula;
  317.         WaveTableObj->DataModified = True;
  318.     }
  319.  
  320.  
  321. /* find out whether its 8 or 16 bits. */
  322. NumBitsType                        WaveTableObjectGetNumBits(WaveTableObjectRec* WaveTableObj)
  323.     {
  324.         CheckPtrExistence(WaveTableObj);
  325.         if (WaveTableObj->WaveTableWindow != NIL)
  326.             {
  327.                 return WaveTableWindowGetNumBits(WaveTableObj->WaveTableWindow);
  328.             }
  329.          else
  330.             {
  331.                 return WaveTableStorageNumBits(WaveTableObj->WaveTableData);
  332.             }
  333.     }
  334.  
  335.  
  336. /* find out how many tables there are in the wave table */
  337. long                                    WaveTableObjectGetNumTables(WaveTableObjectRec* WaveTableObj)
  338.     {
  339.         CheckPtrExistence(WaveTableObj);
  340.         if (WaveTableObj->WaveTableWindow != NIL)
  341.             {
  342.                 return WaveTableWindowGetNumTables(WaveTableObj->WaveTableWindow);
  343.             }
  344.          else
  345.             {
  346.                 return WaveTableStorageNumTables(WaveTableObj->WaveTableData);
  347.             }
  348.     }
  349.  
  350.  
  351. /* find out how many entries there are in a single table */
  352. long                                    WaveTableObjectEntriesPerTable(WaveTableObjectRec* WaveTableObj)
  353.     {
  354.         CheckPtrExistence(WaveTableObj);
  355.         if (WaveTableObj->WaveTableWindow != NIL)
  356.             {
  357.                 return WaveTableWindowGetNumFramesPerTable(WaveTableObj->WaveTableWindow);
  358.             }
  359.          else
  360.             {
  361.                 return WaveTableStorageNumFramesPerTable(WaveTableObj->WaveTableData);
  362.             }
  363.     }
  364.  
  365.  
  366. /* get the raw data for a particular wave table.  this returns the actual data, so */
  367. /* don't dispose it.  if any operations are performed on the wave table, this */
  368. /* pointer may become invalid.  the data is in the following format: */
  369. /*  - 8-bit:  array of signed bytes */
  370. /*  - 16-bit:  array of signed short integers */
  371. char*                                    WaveTableObjectGetRawSlice(WaveTableObjectRec* WaveTableObj,
  372.                                                 long WaveTableIndex)
  373.     {
  374.         CheckPtrExistence(WaveTableObj);
  375.         ERROR((WaveTableIndex < 0) || (WaveTableIndex
  376.             >= WaveTableObjectGetNumTables(WaveTableObj)),PRERR(ForceAbort,
  377.             "WaveTableObjectGetRawSlice:  index out of range"));
  378.         if (WaveTableObj->WaveTableWindow != NIL)
  379.             {
  380.                 if (!WaveTableWindowForceWaveTableUpdate(WaveTableObj->WaveTableWindow))
  381.                     {
  382.                         return NIL;
  383.                     }
  384.             }
  385.         return (char*)WaveTableStorageGetTable(WaveTableObj->WaveTableData,WaveTableIndex);
  386.     }
  387.  
  388.  
  389. /* put new data into the wave table. the object becomes the owner of all data passed in. */
  390. void                                    WaveTableObjectPutNewData(WaveTableObjectRec* WaveTableObj,
  391.                                                 struct WaveTableStorageRec* NewWaveTable)
  392.     {
  393.         CheckPtrExistence(WaveTableObj);
  394.         CheckPtrExistence(NewWaveTable);
  395.         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  396.         WaveTableObj->WaveTableData = NewWaveTable;
  397.         WaveTableObj->DataModified = True;
  398.     }
  399.  
  400.  
  401. /* tell the wave table to open it's editor window */
  402. MyBoolean                            WaveTableObjectOpenWindow(WaveTableObjectRec* WaveTableObj)
  403.     {
  404.         CheckPtrExistence(WaveTableObj);
  405.         if (WaveTableObj->WaveTableWindow == NIL)
  406.             {
  407.                 WaveTableObj->WaveTableWindow = NewWaveTableWindow(WaveTableObj->MainWindow,
  408.                     WaveTableObj,WaveTableObj->CodeCenter,WaveTableObj->WaveTableList,
  409.                     WaveTableObj->WaveTableData,WaveTableObj->SavedWindowXLoc,
  410.                     WaveTableObj->SavedWindowYLoc,WaveTableObj->SavedWindowWidth,
  411.                     WaveTableObj->SavedWindowHeight);
  412.             }
  413.          else
  414.             {
  415.                 WaveTableWindowBringToTop(WaveTableObj->WaveTableWindow);
  416.             }
  417.         return (WaveTableObj->WaveTableWindow != NIL);
  418.     }
  419.  
  420.  
  421. /* this is called by the window when it is closing to notify the object. */
  422. /* the object should not take any action. */
  423. void                                    WaveTableObjectClosingWindowNotify(
  424.                                                 WaveTableObjectRec* WaveTableObj, short NewX, short NewY,
  425.                                                 short NewWidth, short NewHeight)
  426.     {
  427.         CheckPtrExistence(WaveTableObj);
  428.         ERROR(WaveTableObj->WaveTableWindow == NIL,PRERR(ForceAbort,
  429.             "WaveTableObjectClosingWindowNotify:  window not open"));
  430.         WaveTableObj->WaveTableWindow = NIL;
  431.         WaveTableObj->SavedWindowXLoc = NewX;
  432.         WaveTableObj->SavedWindowYLoc = NewY;
  433.         WaveTableObj->SavedWindowWidth = NewWidth;
  434.         WaveTableObj->SavedWindowHeight = NewHeight;
  435.     }
  436.  
  437.  
  438. /* obtain a fixedpoint array of data.  NIL is returned if there isn't enough memory. */
  439. largefixedsigned*            WaveTableObjectGetFixed(WaveTableObjectRec* WaveTableObj)
  440.     {
  441.         largefixedsigned*        Array;
  442.  
  443.         CheckPtrExistence(WaveTableObj);
  444.         if (WaveTableObj->WaveTableWindow == NIL)
  445.             {
  446.                 long                                TableLimit;
  447.                 long                                FrameLimit;
  448.                 long                                TableScan;
  449.  
  450.                 TableLimit = WaveTableObjectGetNumTables(WaveTableObj);
  451.                 FrameLimit = WaveTableObjectEntriesPerTable(WaveTableObj);
  452.                 Array = (largefixedsigned*)AllocPtrCanFail(TableLimit * FrameLimit
  453.                     * sizeof(largefixedsigned),"WaveTableFixedArrayCopy");
  454.                 if (Array != NIL)
  455.                     {
  456.                         for (TableScan = 0; TableScan < TableLimit; TableScan += 1)
  457.                             {
  458.                                 long                                FrameScan;
  459.  
  460.                                 for (FrameScan = 0; FrameScan < FrameLimit; FrameScan += 1)
  461.                                     {
  462.                                         PRNGCHK(Array,&(Array[TableScan * FrameLimit + FrameScan]),
  463.                                             sizeof(Array[TableScan * FrameLimit + FrameScan]));
  464.                                         Array[TableScan * FrameLimit + FrameScan]
  465.                                             = WaveTableStorageGetFrame(WaveTableObj->WaveTableData,
  466.                                             TableScan,FrameScan);
  467.                                     }
  468.                             }
  469.                     }
  470.             }
  471.          else
  472.             {
  473.                 Array = WaveTableWindowGetWaveArray(WaveTableObj->WaveTableWindow);
  474.             }
  475.         return Array;
  476.     }
  477.  
  478.  
  479. /* the document's name has changed, so we need to update the windows */
  480. void                                    WaveTableObjectGlobalNameChange(WaveTableObjectRec* WaveTableObj,
  481.                                                 char* NewFilename)
  482.     {
  483.         CheckPtrExistence(WaveTableObj);
  484.         if (WaveTableObj->WaveTableWindow != NIL)
  485.             {
  486.                 WaveTableWindowGlobalNameChange(WaveTableObj->WaveTableWindow,NewFilename);
  487.             }
  488.     }
  489.  
  490.  
  491. /* get the test attack duration */
  492. double                                WaveTableObjectGetTestAttack(WaveTableObjectRec* WaveTableObj)
  493.     {
  494.         CheckPtrExistence(WaveTableObj);
  495.         if (WaveTableObj->WaveTableWindow != NIL)
  496.             {
  497.                 return WaveTableWindowGetAscendingDuration(WaveTableObj->WaveTableWindow);
  498.             }
  499.          else
  500.             {
  501.                 return WaveTableObj->TestAttackDuration;
  502.             }
  503.     }
  504.  
  505.  
  506. /* put a new test attack duration */
  507. void                                    SetWaveTableObjectTestAttack(WaveTableObjectRec* WaveTableObj,
  508.                                                 double NewTestAttack)
  509.     {
  510.         CheckPtrExistence(WaveTableObj);
  511.         WaveTableObj->TestAttackDuration = NewTestAttack;
  512.     }
  513.  
  514.  
  515. /* get the test decay duration */
  516. double                                WaveTableObjectGetTestDecay(WaveTableObjectRec* WaveTableObj)
  517.     {
  518.         CheckPtrExistence(WaveTableObj);
  519.         if (WaveTableObj->WaveTableWindow != NIL)
  520.             {
  521.                 return WaveTableWindowGetDescendingDuration(WaveTableObj->WaveTableWindow);
  522.             }
  523.          else
  524.             {
  525.                 return WaveTableObj->TestDecayDuration;
  526.             }
  527.     }
  528.  
  529.  
  530. /* put a new test decay duration */
  531. void                                    SetWaveTableObjectTestDecay(WaveTableObjectRec* WaveTableObj,
  532.                                                 double NewTestDecay)
  533.     {
  534.         CheckPtrExistence(WaveTableObj);
  535.         WaveTableObj->TestDecayDuration = NewTestDecay;
  536.     }
  537.  
  538.  
  539. /* get the test sampling rate */
  540. long                                    WaveTableObjectGetTestSamplingRate(WaveTableObjectRec* WaveTableObj)
  541.     {
  542.         CheckPtrExistence(WaveTableObj);
  543.         if (WaveTableObj->WaveTableWindow != NIL)
  544.             {
  545.                 return WaveTableWindowGetTestSamplingRate(WaveTableObj->WaveTableWindow);
  546.             }
  547.          else
  548.             {
  549.                 return WaveTableObj->TestSamplingRate;
  550.             }
  551.     }
  552.  
  553.  
  554. /* put a new test sampling rate */
  555. void                                    SetWaveTableObjectTestSamplingRate(WaveTableObjectRec* WaveTableObj,
  556.                                                 long NewTestSamplingRate)
  557.     {
  558.         CheckPtrExistence(WaveTableObj);
  559.         WaveTableObj->TestSamplingRate = NewTestSamplingRate;
  560.     }
  561.  
  562.  
  563. /* get the test pitch */
  564. double                                WaveTableObjectGetTestPitch(WaveTableObjectRec* WaveTableObj)
  565.     {
  566.         CheckPtrExistence(WaveTableObj);
  567.         if (WaveTableObj->WaveTableWindow != NIL)
  568.             {
  569.                 return WaveTableWindowGetPitch(WaveTableObj->WaveTableWindow);
  570.             }
  571.          else
  572.             {
  573.                 return WaveTableObj->TestFrequency;
  574.             }
  575.     }
  576.  
  577.  
  578. /* put a new test pitch */
  579. void                                    SetWaveTableObjectTestPitch(WaveTableObjectRec* WaveTableObj,
  580.                                                 double NewTestPitch)
  581.     {
  582.         CheckPtrExistence(WaveTableObj);
  583.         WaveTableObj->TestFrequency = NewTestPitch;
  584.     }
  585.  
  586.  
  587. /* Wave Table Object Subblock Format: */
  588. /*   1-byte format version number */
  589. /*       should be 1 */
  590. /*   2-byte little endian window X location (signed; origin at upper left corner) */
  591. /*   2-byte little endian window Y location */
  592. /*   2-byte little endian window width */
  593. /*   2-byte little endian window height */
  594. /*   4-byte little endian wave table name length descriptor */
  595. /*   n-byte name string (line feed = 0x0a) */
  596. /*   4-byte little endian wave table formula length descriptor */
  597. /*   n-byte formula string (line feed = 0x0a) */
  598. /*   4-byte little endian large integer encoded test attack duration. */
  599. /*       large integer coded decimal is decimal * 1000000 with a */
  600. /*       range of -1999.999999 to 1999.999999 */
  601. /*   4-byte little endian large integer encoded test decay duration. */
  602. /*   4-byte little endian test frequency fractional portion */
  603. /*       unsigned; divide by 2^32 to get the actual fraction */
  604. /*   4-byte little endian test frequency integer portion */
  605. /*       total test frequency should be between 0.01 and 1e6 */
  606. /*   4-byte little endian test sampling rate */
  607. /*       should be between 100 and 65535 */
  608. /*   4-byte little endian number of tables */
  609. /*   4-byte little endian number of frames per table */
  610. /*       must be an integral power or 2 between 2 and 65536 */
  611. /*   1-byte number of bits specifier */
  612. /*       must be 8 or 16 */
  613. /*   n-byte sample data for the wave table */
  614. /*       data is stored as follows:  each table is stored consecutively starting */
  615. /*       with the table numbered 0.  in each table, each sample frame is stored */
  616. /*       consecutively as a signed 2s complement value.  8-bit sample frames */
  617. /*       use 1 byte each.  16-bit sample frames use 2 bytes and are stored little */
  618. /*       endian. */
  619.  
  620.  
  621. /* load an object from the file */
  622. FileLoadingErrors            WaveTableObjectNewFromFile(WaveTableObjectRec** ObjectOut,
  623.                                                 struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  624.                                                 struct MainWindowRec* MainWindow,
  625.                                                 struct WaveTableListRec* WaveTableList)
  626.     {
  627.         unsigned char                UnsignedChar;
  628.         WaveTableObjectRec*    WaveTableObj;
  629.         FileLoadingErrors        Error;
  630.         signed short                SignedShort;
  631.         unsigned long                UnsignedLong;
  632.         signed long                    SignedLong;
  633.         signed long                    NumberOfTables;
  634.         signed long                    NumberOfFrames;
  635.         NumBitsType                    NumberOfBits;
  636.         long                                Scan;
  637.  
  638.         CheckPtrExistence(Input);
  639.         CheckPtrExistence(CodeCenter);
  640.         CheckPtrExistence(MainWindow);
  641.         CheckPtrExistence(WaveTableList);
  642.  
  643.         WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
  644.             "WaveTableObjectRec");
  645.         if (WaveTableObj == NIL)
  646.             {
  647.                 Error = eFileLoadOutOfMemory;
  648.              FailurePoint1:
  649.                 return Error;
  650.             }
  651.  
  652.         /*   1-byte format version number */
  653.         /*       should be 1 */
  654.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  655.             {
  656.                 Error = eFileLoadDiskError;
  657.              FailurePoint2:
  658.                 ReleasePtr((char*)WaveTableObj);
  659.                 goto FailurePoint1;
  660.             }
  661.         if (UnsignedChar != 1)
  662.             {
  663.                 Error = eFileLoadBadFormat;
  664.              FailurePoint3:
  665.                 goto FailurePoint2;
  666.             }
  667.  
  668.         /*   2-byte little endian window X location (signed; origin at upper left corner) */
  669.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  670.             {
  671.                 Error = eFileLoadDiskError;
  672.              FailurePoint4:
  673.                 goto FailurePoint3;
  674.             }
  675.         WaveTableObj->SavedWindowXLoc = SignedShort;
  676.  
  677.         /*   2-byte little endian window Y location */
  678.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  679.             {
  680.                 Error = eFileLoadDiskError;
  681.              FailurePoint5:
  682.                 goto FailurePoint4;
  683.             }
  684.         WaveTableObj->SavedWindowYLoc = SignedShort;
  685.  
  686.         /*   2-byte little endian window width */
  687.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  688.             {
  689.                 Error = eFileLoadDiskError;
  690.              FailurePoint6:
  691.                 goto FailurePoint5;
  692.             }
  693.         WaveTableObj->SavedWindowWidth = SignedShort;
  694.  
  695.         /*   2-byte little endian window height */
  696.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  697.             {
  698.                 Error = eFileLoadDiskError;
  699.              FailurePoint7:
  700.                 goto FailurePoint6;
  701.             }
  702.         WaveTableObj->SavedWindowHeight = SignedShort;
  703.  
  704.         /*   4-byte little endian wave table name length descriptor */
  705.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  706.             {
  707.                 Error = eFileLoadDiskError;
  708.              FailurePoint8:
  709.                 goto FailurePoint7;
  710.             }
  711.         if (SignedLong < 0)
  712.             {
  713.                 Error = eFileLoadBadFormat;
  714.              FailurePoint9:
  715.                 goto FailurePoint8;
  716.             }
  717.  
  718.         /*   n-byte name string (line feed = 0x0a) */
  719.         WaveTableObj->Name = AllocPtrCanFail(SignedLong,"WaveTableObjectRec:  name");
  720.         if (WaveTableObj->Name == NIL)
  721.             {
  722.                 Error = eFileLoadOutOfMemory;
  723.              FailurePoint10:
  724.                 goto FailurePoint9;
  725.             }
  726.         if (!ReadBufferedInput(Input,SignedLong,WaveTableObj->Name))
  727.             {
  728.                 Error = eFileLoadDiskError;
  729.              FailurePoint11:
  730.                 ReleasePtr(WaveTableObj->Name);
  731.                 goto FailurePoint10;
  732.             }
  733.  
  734.         /*   4-byte little endian wave table formula length descriptor */
  735.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  736.             {
  737.                 Error = eFileLoadDiskError;
  738.              FailurePoint12:
  739.                 goto FailurePoint11;
  740.             }
  741.         if (SignedLong < 0)
  742.             {
  743.                 Error = eFileLoadBadFormat;
  744.              FailurePoint13:
  745.                 goto FailurePoint12;
  746.             }
  747.  
  748.         /*   n-byte formula string (line feed = 0x0a) */
  749.         WaveTableObj->WaveTableFormula = AllocPtrCanFail(SignedLong,
  750.             "WaveTableObjectRec:  formula");
  751.         if (WaveTableObj->WaveTableFormula == NIL)
  752.             {
  753.                 Error = eFileLoadOutOfMemory;
  754.              FailurePoint14:
  755.                 goto FailurePoint13;
  756.             }
  757.         if (!ReadBufferedInput(Input,SignedLong,WaveTableObj->WaveTableFormula))
  758.             {
  759.                 Error = eFileLoadDiskError;
  760.              FailurePoint15:
  761.                 ReleasePtr(WaveTableObj->WaveTableFormula);
  762.                 goto FailurePoint14;
  763.             }
  764.  
  765.         /*   4-byte little endian large integer encoded test attack duration. */
  766.         /*       large integer coded decimal is decimal * 1000000 with a */
  767.         /*       range of -1999.999999 to 1999.999999 */
  768.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  769.             {
  770.                 Error = eFileLoadDiskError;
  771.              FailurePoint16:
  772.                 goto FailurePoint15;
  773.             }
  774.         WaveTableObj->TestAttackDuration = LargeBCD2Double(SignedLong);
  775.         if (WaveTableObj->TestAttackDuration < 0)
  776.             {
  777.                 WaveTableObj->TestAttackDuration = 0;
  778.             }
  779.  
  780.         /*   4-byte little endian large integer encoded test decay duration. */
  781.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  782.             {
  783.                 Error = eFileLoadDiskError;
  784.              FailurePoint17:
  785.                 goto FailurePoint16;
  786.             }
  787.         WaveTableObj->TestDecayDuration = LargeBCD2Double(SignedLong);
  788.         if (WaveTableObj->TestDecayDuration < 0)
  789.             {
  790.                 WaveTableObj->TestDecayDuration = 0;
  791.             }
  792.  
  793.         /*   4-byte little endian test frequency fractional portion */
  794.         /*       unsigned; divide by 2^32 to get the actual fraction */
  795.         if (!ReadBufferedUnsignedLongLittleEndian(Input,&UnsignedLong))
  796.             {
  797.                 Error = eFileLoadDiskError;
  798.              FailurePoint18:
  799.                 goto FailurePoint17;
  800.             }
  801.         WaveTableObj->TestFrequency = (double)UnsignedLong / 4294967296.0L;
  802.  
  803.         /*   4-byte little endian test frequency integer portion */
  804.         /*       total test frequency should be between 0.01 and 1e6 */
  805.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  806.             {
  807.                 Error = eFileLoadDiskError;
  808.              FailurePoint19:
  809.                 goto FailurePoint18;
  810.             }
  811.         WaveTableObj->TestFrequency += SignedLong;
  812.         if (WaveTableObj->TestFrequency < MINNATURALFREQ)
  813.             {
  814.                 WaveTableObj->TestFrequency = MINNATURALFREQ;
  815.             }
  816.         if (WaveTableObj->TestFrequency > MAXNATURALFREQ)
  817.             {
  818.                 WaveTableObj->TestFrequency = MAXNATURALFREQ;
  819.             }
  820.  
  821.         /*   4-byte little endian test sampling rate */
  822.         /*       should be between 100 and 65535 */
  823.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  824.             {
  825.                 Error = eFileLoadDiskError;
  826.              FailurePoint20:
  827.                 goto FailurePoint19;
  828.             }
  829.         if (SignedLong < MINSAMPLINGRATE)
  830.             {
  831.                 SignedLong = MINSAMPLINGRATE;
  832.             }
  833.         if (SignedLong > MAXSAMPLINGRATE)
  834.             {
  835.                 SignedLong = MAXSAMPLINGRATE;
  836.             }
  837.         WaveTableObj->TestSamplingRate = SignedLong;
  838.  
  839.         /*   4-byte little endian number of tables */
  840.         if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfTables))
  841.             {
  842.                 Error = eFileLoadDiskError;
  843.              FailurePoint21:
  844.                 goto FailurePoint20;
  845.             }
  846.         if (NumberOfTables < 0)
  847.             {
  848.                 Error = eFileLoadBadFormat;
  849.              FailurePoint22:
  850.                 goto FailurePoint21;
  851.             }
  852.  
  853.         /*   4-byte little endian number of frames per table */
  854.         /*       must be an integral power or 2 between 2 and 65536 */
  855.         if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfFrames))
  856.             {
  857.                 Error = eFileLoadDiskError;
  858.              FailurePoint23:
  859.                 goto FailurePoint22;
  860.             }
  861.         if ((NumberOfFrames != 2) && (NumberOfFrames != 4) && (NumberOfFrames != 8)
  862.             && (NumberOfFrames != 16) && (NumberOfFrames != 32) && (NumberOfFrames != 64)
  863.             && (NumberOfFrames != 128) && (NumberOfFrames != 256) && (NumberOfFrames != 512)
  864.             && (NumberOfFrames != 1024) && (NumberOfFrames != 2048)
  865.             && (NumberOfFrames != 4096) && (NumberOfFrames != 8192)
  866.             && (NumberOfFrames != 16384) && (NumberOfFrames != 32768)
  867.             && (NumberOfFrames != 65536))
  868.             {
  869.                 Error = eFileLoadBadFormat;
  870.              FailurePoint24:
  871.                 goto FailurePoint23;
  872.             }
  873.  
  874.         /*   1-byte number of bits specifier */
  875.         /*       must be 8 or 16 */
  876.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  877.             {
  878.                 Error = eFileLoadDiskError;
  879.              FailurePoint25:
  880.                 goto FailurePoint24;
  881.             }
  882.         if (UnsignedChar == 8)
  883.             {
  884.                 NumberOfBits = eSample8bit;
  885.             }
  886.         else if (UnsignedChar == 16)
  887.             {
  888.                 NumberOfBits = eSample16bit;
  889.             }
  890.         else
  891.             {
  892.                 Error = eFileLoadBadFormat;
  893.              FailurePoint26:
  894.                 goto FailurePoint25;
  895.             }
  896.  
  897.         /*   n-byte sample data for the wave table */
  898.         /*       data is stored as follows:  each table is stored consecutively starting */
  899.         /*       with the table numbered 0.  in each table, each sample frame is stored */
  900.         /*       consecutively as a signed 2s complement value.  8-bit sample frames */
  901.         /*       use 1 byte each.  16-bit sample frames use 2 bytes and are stored little */
  902.         /*       endian. */
  903.         WaveTableObj->WaveTableData = NewWaveTableStorage(NumberOfBits,NumberOfFrames);
  904.         if (WaveTableObj->WaveTableData == NIL)
  905.             {
  906.                 Error = eFileLoadOutOfMemory;
  907.              FailurePoint27:
  908.                 goto FailurePoint26;
  909.             }
  910.         for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  911.             {
  912.                 if (!WaveTableStorageAppendEntry(WaveTableObj->WaveTableData))
  913.                     {
  914.                         Error = eFileLoadOutOfMemory;
  915.                      FailurePoint28:
  916.                         DisposeWaveTableStorage(WaveTableObj->WaveTableData);
  917.                         goto FailurePoint27;
  918.                     }
  919.             }
  920.         switch (NumberOfBits)
  921.             {
  922.                 default:
  923.                     EXECUTE(PRERR(ForceAbort,"WaveTableObjectNewFromFile:  bad number of bits"));
  924.                     break;
  925.                 case eSample8bit:
  926.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  927.                         {
  928.                             long                            Index;
  929.  
  930.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  931.                                 {
  932.                                     signed char                SamplePoint;
  933.  
  934.                                     if (!ReadBufferedSignedChar(Input,&SamplePoint))
  935.                                         {
  936.                                             Error = eFileLoadDiskError;
  937.                                             goto FailurePoint28;
  938.                                         }
  939.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,Index,
  940.                                         double2largefixed((double)SamplePoint / MAX8BIT));
  941.                                 }
  942.                         }
  943.                     break;
  944.                 case eSample16bit:
  945.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  946.                         {
  947.                             long                            Index;
  948.  
  949.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  950.                                 {
  951.                                     signed short            SamplePoint;
  952.  
  953.                                     if (!ReadBufferedSignedShortLittleEndian(Input,&SamplePoint))
  954.                                         {
  955.                                             Error = eFileLoadDiskError;
  956.                                             goto FailurePoint28;
  957.                                         }
  958.                                     WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,Index,
  959.                                         double2largefixed((double)SamplePoint / MAX16BIT));
  960.                                 }
  961.                         }
  962.                     break;
  963.             }
  964.  
  965.         /* fill in the other fields */
  966.         WaveTableObj->DataModified = False;
  967.         WaveTableObj->WaveTableWindow = NIL;
  968.         WaveTableObj->CodeCenter = CodeCenter;
  969.         WaveTableObj->MainWindow = MainWindow;
  970.         WaveTableObj->WaveTableList = WaveTableList;
  971.  
  972.         *ObjectOut = WaveTableObj;
  973.         return eFileLoadNoError;
  974.     }
  975.  
  976.  
  977. /* write the object out to the file. */
  978. FileLoadingErrors            WaveTableObjectWriteDataOut(WaveTableObjectRec* WaveTableObj,
  979.                                                 struct BufferedOutputRec* Output)
  980.     {
  981.         char*                                StringTemp;
  982.         double                            FrequencyTemp;
  983.         long                                NumberOfTables;
  984.         long                                NumberOfFrames;
  985.         NumBitsType                    NumberOfBits;
  986.         long                                Scan;
  987.  
  988.         CheckPtrExistence(WaveTableObj);
  989.         CheckPtrExistence(Output);
  990.  
  991.         if (WaveTableObj->WaveTableWindow != NIL)
  992.             {
  993.                 if (!WaveTableWindowForceWaveTableUpdate(WaveTableObj->WaveTableWindow))
  994.                     {
  995.                         return eFileLoadOutOfMemory;
  996.                     }
  997.             }
  998.  
  999.         /*   1-byte format version number */
  1000.         /*       should be 1 */
  1001.         if (!WriteBufferedUnsignedChar(Output,1))
  1002.             {
  1003.                 return eFileLoadDiskError;
  1004.             }
  1005.  
  1006.         /*   2-byte little endian window X location (signed; origin at upper left corner) */
  1007.         /* note that if the window is open when the file is saved, then the most */
  1008.         /* recent coordinates of the window will not be saved */
  1009.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowXLoc))
  1010.             {
  1011.                 return eFileLoadDiskError;
  1012.             }
  1013.  
  1014.         /*   2-byte little endian window Y location */
  1015.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowYLoc))
  1016.             {
  1017.                 return eFileLoadDiskError;
  1018.             }
  1019.  
  1020.         /*   2-byte little endian window width */
  1021.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowWidth))
  1022.             {
  1023.                 return eFileLoadDiskError;
  1024.             }
  1025.  
  1026.         /*   2-byte little endian window height */
  1027.         if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowHeight))
  1028.             {
  1029.                 return eFileLoadDiskError;
  1030.             }
  1031.  
  1032.         /*   4-byte little endian wave table name length descriptor */
  1033.         StringTemp = WaveTableObjectGetNameCopy(WaveTableObj);
  1034.         if (StringTemp == NIL)
  1035.             {
  1036.                 return eFileLoadOutOfMemory;
  1037.             }
  1038.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1039.             {
  1040.                 ReleasePtr(StringTemp);
  1041.                 return eFileLoadDiskError;
  1042.             }
  1043.  
  1044.         /*   n-byte name string (line feed = 0x0a) */
  1045.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1046.             {
  1047.                 ReleasePtr(StringTemp);
  1048.                 return eFileLoadDiskError;
  1049.             }
  1050.         ReleasePtr(StringTemp);
  1051.  
  1052.         /*   4-byte little endian wave table formula length descriptor */
  1053.         StringTemp = WaveTableObjectGetFormulaCopy(WaveTableObj);
  1054.         if (StringTemp == NIL)
  1055.             {
  1056.                 return eFileLoadOutOfMemory;
  1057.             }
  1058.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1059.             {
  1060.                 ReleasePtr(StringTemp);
  1061.                 return eFileLoadDiskError;
  1062.             }
  1063.  
  1064.         /*   n-byte formula string (line feed = 0x0a) */
  1065.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1066.             {
  1067.                 ReleasePtr(StringTemp);
  1068.                 return eFileLoadDiskError;
  1069.             }
  1070.         ReleasePtr(StringTemp);
  1071.  
  1072.         /*   4-byte little endian large integer encoded test attack duration. */
  1073.         /*       large integer coded decimal is decimal * 1000000 with a */
  1074.         /*       range of -1999.999999 to 1999.999999 */
  1075.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1076.             Double2LargeBCD(WaveTableObjectGetTestAttack(WaveTableObj))))
  1077.             {
  1078.                 return eFileLoadDiskError;
  1079.             }
  1080.  
  1081.         /*   4-byte little endian large integer encoded test decay duration. */
  1082.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1083.             Double2LargeBCD(WaveTableObjectGetTestDecay(WaveTableObj))))
  1084.             {
  1085.                 return eFileLoadDiskError;
  1086.             }
  1087.  
  1088.         /*   4-byte little endian test frequency fractional portion */
  1089.         /*       unsigned; divide by 2^32 to get the actual fraction */
  1090.         FrequencyTemp = WaveTableObjectGetTestPitch(WaveTableObj);
  1091.         if (!WriteBufferedUnsignedLongLittleEndian(Output,
  1092.             (unsigned long)((FrequencyTemp - (long)FrequencyTemp) * 4294967296.0L)))
  1093.             {
  1094.                 return eFileLoadDiskError;
  1095.             }
  1096.  
  1097.         /*   4-byte little endian test frequency integer portion */
  1098.         /*       total test frequency should be between 0.01 and 1e6 */
  1099.         if (!WriteBufferedSignedLongLittleEndian(Output,(long)FrequencyTemp))
  1100.             {
  1101.                 return eFileLoadDiskError;
  1102.             }
  1103.  
  1104.         /*   4-byte little endian test sampling rate */
  1105.         /*       should be between 100 and 65535 */
  1106.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1107.             WaveTableObjectGetTestSamplingRate(WaveTableObj)))
  1108.             {
  1109.                 return eFileLoadDiskError;
  1110.             }
  1111.  
  1112.         /*   4-byte little endian number of tables */
  1113.         NumberOfTables = WaveTableObjectGetNumTables(WaveTableObj);
  1114.         if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfTables))
  1115.             {
  1116.                 return eFileLoadDiskError;
  1117.             }
  1118.  
  1119.         /*   4-byte little endian number of frames per table */
  1120.         /*       must be an integral power or 2 between 2 and 65536 */
  1121.         NumberOfFrames = WaveTableObjectEntriesPerTable(WaveTableObj);
  1122.         if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfFrames))
  1123.             {
  1124.                 return eFileLoadDiskError;
  1125.             }
  1126.  
  1127.         /*   1-byte number of bits specifier */
  1128.         /*       must be 8 or 16 */
  1129.         NumberOfBits = WaveTableObjectGetNumBits(WaveTableObj);
  1130.         switch (NumberOfBits)
  1131.             {
  1132.                 default:
  1133.                     EXECUTE(PRERR(ForceAbort,"WaveTableObjectWriteDataOut:  bad number of bits"));
  1134.                     break;
  1135.                 case eSample8bit:
  1136.                     if (!WriteBufferedUnsignedChar(Output,8))
  1137.                         {
  1138.                             return eFileLoadDiskError;
  1139.                         }
  1140.                     break;
  1141.                 case eSample16bit:
  1142.                     if (!WriteBufferedUnsignedChar(Output,16))
  1143.                         {
  1144.                             return eFileLoadDiskError;
  1145.                         }
  1146.                     break;
  1147.             }
  1148.  
  1149.         /*   n-byte sample data for the wave table */
  1150.         /*       data is stored as follows:  each table is stored consecutively starting */
  1151.         /*       with the table numbered 0.  in each table, each sample frame is stored */
  1152.         /*       consecutively as a signed 2s complement value.  8-bit sample frames */
  1153.         /*       use 1 byte each.  16-bit sample frames use 2 bytes and are stored little */
  1154.         /*       endian. */
  1155.         switch (NumberOfBits)
  1156.             {
  1157.                 default:
  1158.                     EXECUTE(PRERR(ForceAbort,"WaveTableObjectWriteDataOut:  bad number of bits"));
  1159.                     break;
  1160.                 case eSample8bit:
  1161.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  1162.                         {
  1163.                             long                            Index;
  1164.                             signed char*            Slice;
  1165.  
  1166.                             Slice = (signed char*)WaveTableObjectGetRawSlice(WaveTableObj,Scan);
  1167.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  1168.                                 {
  1169.                                     PRNGCHK(Slice,&(Slice[Index]),sizeof(Slice[Index]));
  1170.                                     if (!WriteBufferedSignedChar(Output,Slice[Index]))
  1171.                                         {
  1172.                                             return eFileLoadDiskError;
  1173.                                         }
  1174.                                 }
  1175.                         }
  1176.                     break;
  1177.                 case eSample16bit:
  1178.                     for (Scan = 0; Scan < NumberOfTables; Scan += 1)
  1179.                         {
  1180.                             long                            Index;
  1181.                             signed short*            Slice;
  1182.  
  1183.                             Slice = (signed short*)WaveTableObjectGetRawSlice(WaveTableObj,Scan);
  1184.                             for (Index = 0; Index < NumberOfFrames; Index += 1)
  1185.                                 {
  1186.                                     PRNGCHK(Slice,&(Slice[Index]),sizeof(Slice[Index]));
  1187.                                     if (!WriteBufferedSignedShortLittleEndian(Output,Slice[Index]))
  1188.                                         {
  1189.                                             return eFileLoadDiskError;
  1190.                                         }
  1191.                                 }
  1192.                         }
  1193.                     break;
  1194.             }
  1195.  
  1196.         return eFileLoadNoError;
  1197.     }
  1198.  
  1199.  
  1200. /* mark wave table object as saved */
  1201. void                                    WaveTableObjectMarkAsSaved(WaveTableObjectRec* WaveTableObj)
  1202.     {
  1203.         CheckPtrExistence(WaveTableObj);
  1204.         if (WaveTableObj->WaveTableWindow != NIL)
  1205.             {
  1206.                 WaveTableWindowWritebackModifiedData(WaveTableObj->WaveTableWindow);
  1207.             }
  1208.         WaveTableObj->DataModified = False;
  1209.     }
  1210.