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

  1. /* WaveTableWindow.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 "WaveTableWindow.h"
  31. #include "MainWindowStuff.h"
  32. #include "CodeCenter.h"
  33. #include "WaveTableList.h"
  34. #include "TextEdit.h"
  35. #include "IconButton.h"
  36. #include "Scroll.h"
  37. #include "SimpleButton.h"
  38. #include "SampleView.h"
  39. #include "WindowDispatcher.h"
  40. #include "WaveTableObject.h"
  41. #include "Memory.h"
  42. #include "Numbers.h"
  43. #include "Array.h"
  44. #include "DataMunging.h"
  45. #include "EditImages.h"
  46. #include "GrowIcon.h"
  47. #include "Main.h"
  48. #include "StringDialog.h"
  49. #include "FindDialog.h"
  50. #include "GlobalWindowMenuList.h"
  51. #include "WaveTableStorage.h"
  52. #include "WaveTableStorageDisplay.h"
  53. #include "SoundOutput.h"
  54. #include "Alert.h"
  55. #include "NumberDialog.h"
  56. #include "WaveTableSizeDialog.h"
  57. #include "CompilerRoot.h"
  58. #include "PcodeObject.h"
  59. #include "PcodeStack.h"
  60. #include "PcodeSystem.h"
  61. #include "FunctionCode.h"
  62.  
  63.  
  64. #define PAGEINCREMENT (1)
  65.  
  66.  
  67. #define WINDOWXSIZE (420)
  68. #define WINDOWYSIZE (300)
  69.  
  70. #define NAMEEDITX (80)
  71. #define NAMEEDITY (1)
  72. #define NAMEEDITWIDTH (80)
  73. #define NAMEEDITHEIGHT (19)
  74.  
  75. #define NAMEX (3)
  76. #define NAMEY (NAMEEDITY + 3)
  77.  
  78. #define FRAMEEDITX (NAMEEDITX)
  79. #define FRAMEEDITY (NAMEEDITY + NAMEEDITHEIGHT + 3)
  80. #define FRAMEEDITWIDTH (NAMEEDITWIDTH)
  81. #define FRAMEEDITHEIGHT (NAMEEDITHEIGHT)
  82.  
  83. #define FRAMEX (NAMEX)
  84. #define FRAMEY (FRAMEEDITY + 3)
  85.  
  86. #define TABLESEDITX (FRAMEEDITX)
  87. #define TABLESEDITY (FRAMEEDITY + FRAMEEDITHEIGHT + 3)
  88. #define TABLESEDITWIDTH (FRAMEEDITWIDTH)
  89. #define TABLESEDITHEIGHT (FRAMEEDITHEIGHT)
  90.  
  91. #define TABLESX (FRAMEX)
  92. #define TABLESY (TABLESEDITY + 3)
  93.  
  94. #define BITS8BUTTONX (10)
  95. #define BITS8BUTTONY (TABLESEDITY + TABLESEDITHEIGHT + 5)
  96. #define BITS8BUTTONWIDTH (32)
  97. #define BITS8BUTTONHEIGHT (32)
  98.  
  99. #define BITS16BUTTONX (BITS8BUTTONX + BITS8BUTTONWIDTH + 1)
  100. #define BITS16BUTTONY (BITS8BUTTONY)
  101. #define BITS16BUTTONWIDTH (BITS8BUTTONWIDTH)
  102. #define BITS16BUTTONHEIGHT (BITS8BUTTONHEIGHT)
  103.  
  104. #define TESTATTACKDURATIONX (TABLESEDITX)
  105. #define TESTATTACKDURATIONY (BITS16BUTTONY + BITS16BUTTONHEIGHT + 5)
  106. #define TESTATTACKDURATIONWIDTH (TABLESEDITWIDTH)
  107. #define TESTATTACKDURATIONHEIGHT (TABLESEDITHEIGHT)
  108.  
  109. #define TESTATTACKX (TABLESX)
  110. #define TESTATTACKY (TESTATTACKDURATIONY + 3)
  111.  
  112. #define TESTDECAYDURATIONX (TESTATTACKDURATIONX)
  113. #define TESTDECAYDURATIONY (TESTATTACKDURATIONY + TESTATTACKDURATIONHEIGHT + 3)
  114. #define TESTDECAYDURATIONWIDTH (TESTATTACKDURATIONWIDTH)
  115. #define TESTDECAYDURATIONHEIGHT (TESTATTACKDURATIONHEIGHT)
  116.  
  117. #define TESTDECAYX (TESTATTACKX)
  118. #define TESTDECAYY (TESTDECAYDURATIONY + 3)
  119.  
  120. #define TESTFREQUENCYX (TESTDECAYDURATIONX)
  121. #define TESTFREQUENCYY (TESTDECAYDURATIONY + TESTDECAYDURATIONHEIGHT + 3)
  122. #define TESTFREQUENCYWIDTH (TESTDECAYDURATIONWIDTH)
  123. #define TESTFREQUENCYHEIGHT (TESTDECAYDURATIONHEIGHT)
  124.  
  125. #define TESTFREQX (TESTDECAYX)
  126. #define TESTFREQY (TESTFREQUENCYY + 3)
  127.  
  128. #define TESTSAMPLINGRATEX (TESTFREQUENCYX)
  129. #define TESTSAMPLINGRATEY (TESTFREQUENCYY + TESTFREQUENCYHEIGHT + 3)
  130. #define TESTSAMPLINGRATEWIDTH (TESTFREQUENCYWIDTH)
  131. #define TESTSAMPLINGRATEHEIGHT (TESTFREQUENCYHEIGHT)
  132.  
  133. #define TESTSAMPLX (TESTFREQX)
  134. #define TESTSAMPLY (TESTSAMPLINGRATEY + 3)
  135.  
  136. #define TESTBUTTONX (10)
  137. #define TESTBUTTONY (TESTSAMPLINGRATEY + TESTSAMPLINGRATEHEIGHT + 5)
  138. #define TESTBUTTONWIDTH (80)
  139. #define TESTBUTTONHEIGHT (21)
  140.  
  141. #define EXPRESSIONEDITX (-1)
  142. #define EXPRESSIONEDITWIDTH(WindowWidth) ((WindowWidth) + 2)
  143. #define EXPRESSIONEDITHEIGHT (80)
  144. #define EXPRESSIONEDITY(WindowHeight) ((WindowHeight) - EXPRESSIONEDITHEIGHT + 1)
  145.  
  146. #define WAVEFORMVIEWX (NAMEEDITX + NAMEEDITWIDTH + 10)
  147. #define WAVEFORMVIEWY (-1)
  148. #define WAVEFORMVIEWWIDTH(WinWidth) ((WinWidth) - WAVEFORMVIEWX + 1)
  149. #define WAVEFORMVIEWHEIGHT(WinHeight) (EXPRESSIONEDITY(WinHeight) - WAVEFORMVIEWY - 16)
  150.  
  151. #define TABLESCROLLY(WinHeight) (WAVEFORMVIEWY + WAVEFORMVIEWHEIGHT(WinHeight) - 1)
  152.  
  153.  
  154. struct WaveTableWindowRec
  155.     {
  156.         MainWindowRec*            MainWindow;
  157.         CodeCenterRec*            CodeCenter;
  158.         WaveTableListRec*        WaveTableList;
  159.         WaveTableObjectRec*    WaveTableObject;
  160.  
  161.         WaveTableStorDispRec*    WaveTableData;
  162.         MyBoolean                        WaveDataModified;
  163.         WaveTableStorDispRec*    UndoBackupWaveTable;
  164.  
  165.         WinType*                        ScreenID;
  166.         TextEditRec*                NameEdit;
  167.         TextEditRec*                FunctionEdit;
  168.         TextEditRec*                NumFramesEdit;
  169.         TextEditRec*                NumTablesEdit;
  170.         TextEditRec*                TestAttackDuration;
  171.         TextEditRec*                TestDecayDuration;
  172.         TextEditRec*                TestFrequency;
  173.         TextEditRec*                TestSamplingRate;
  174.         TextEditRec*                ActiveTextEdit;
  175.         SimpleButtonRec*        TestButton;
  176.         IconButtonRec*            Bits8Button;
  177.         IconButtonRec*            Bits16Button;
  178.         ScrollRec*                    TableScroll;
  179.         long                                CurrentlyVisibleTable;
  180.         GenericWindowRec*        MyGenericWindow; /* how the window event dispatcher knows us */
  181.         MenuItemType*                MyMenuItem;
  182.     };
  183.  
  184.  
  185. /* create a new wave table window. */
  186. WaveTableWindowRec*    NewWaveTableWindow(struct MainWindowRec* MainWindow,
  187.                                             struct WaveTableObjectRec* WaveTableObject,
  188.                                             struct CodeCenterRec* CodeCenter,
  189.                                             struct WaveTableListRec* WaveTableList,
  190.                                             struct WaveTableStorageRec* WaveData,
  191.                                             OrdType WinX, OrdType WinY, OrdType WinWidth, OrdType WinHeight)
  192.     {
  193.         WaveTableWindowRec*        Window;
  194.         char*                                    StringTemp;
  195.         long                                    Scan;
  196.         long                                    Limit;
  197.  
  198.         CheckPtrExistence(MainWindow);
  199.         CheckPtrExistence(WaveTableObject);
  200.         CheckPtrExistence(CodeCenter);
  201.         CheckPtrExistence(WaveTableList);
  202.         CheckPtrExistence(WaveData);
  203.  
  204.         /* deal with window placement */
  205.         if ((WinWidth < 100) || (WinHeight < 100) || ((eOptionKey & CheckModifiers()) != 0))
  206.             {
  207.                 WinX = 1 + WindowOtherEdgeWidths(eDocumentWindow);
  208.                 WinY = 1 + WindowTitleBarHeight(eDocumentWindow);
  209.                 WinWidth = WINDOWXSIZE;
  210.                 WinHeight = WINDOWYSIZE;
  211.             }
  212.         MakeWindowFitOnScreen(&WinX,&WinY,&WinWidth,&WinHeight);
  213.  
  214.         Window = (WaveTableWindowRec*)AllocPtrCanFail(sizeof(WaveTableWindowRec),
  215.             "WaveTableWindowRec");
  216.         if (Window == NIL)
  217.             {
  218.              FailurePoint1:
  219.                 return NIL;
  220.             }
  221.         Window->MainWindow = MainWindow;
  222.         Window->WaveTableObject = WaveTableObject;
  223.         Window->CodeCenter = CodeCenter;
  224.         Window->WaveTableList = WaveTableList;
  225.  
  226.         Window->ScreenID = MakeNewWindow(eDocumentWindow,eWindowClosable,
  227.             eWindowZoomable,eWindowResizable,WinX,WinY,WinWidth,WinHeight,
  228.             (void (*)(void*))&WaveTableWindowUpdator,Window);
  229.         if (Window->ScreenID == 0)
  230.             {
  231.              FailurePoint2:
  232.                 ReleasePtr((char*)Window);
  233.                 goto FailurePoint1;
  234.             }
  235.  
  236.         Window->NameEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  237.             GetScreenFont(),9,NAMEEDITX,NAMEEDITY,NAMEEDITWIDTH,NAMEEDITHEIGHT);
  238.         if (Window->NameEdit == NIL)
  239.             {
  240.              FailurePoint3:
  241.                 KillWindow(Window->ScreenID);
  242.                 goto FailurePoint2;
  243.             }
  244.         StringTemp = WaveTableObjectGetNameCopy(WaveTableObject);
  245.         if (StringTemp == NIL)
  246.             {
  247.              FailurePoint4:
  248.                 DisposeTextEdit(Window->NameEdit);
  249.                 goto FailurePoint3;
  250.             }
  251.         TextEditNewRawData(Window->NameEdit,StringTemp,"\x0a");
  252.         ReleasePtr(StringTemp);
  253.         TextEditHasBeenSaved(Window->NameEdit);
  254.  
  255.         Window->FunctionEdit = NewTextEdit(Window->ScreenID,eTEVScrollBar | eTEHScrollBar,
  256.             GetMonospacedFont(),9,EXPRESSIONEDITX,EXPRESSIONEDITY(WinHeight),
  257.             EXPRESSIONEDITWIDTH(WinWidth),EXPRESSIONEDITHEIGHT);
  258.         if (Window->FunctionEdit == NIL)
  259.             {
  260.              FailurePoint5:
  261.                 goto FailurePoint4;
  262.             }
  263.         StringTemp = WaveTableObjectGetFormulaCopy(WaveTableObject);
  264.         SetTextEditTabSize(Window->FunctionEdit,MainWindowGetTabSize(MainWindow));
  265.         if (StringTemp == NIL)
  266.             {
  267.              FailurePoint6:
  268.                 DisposeTextEdit(Window->FunctionEdit);
  269.                 goto FailurePoint5;
  270.             }
  271.         TextEditNewRawData(Window->FunctionEdit,StringTemp,"\x0a");
  272.         ReleasePtr(StringTemp);
  273.         TextEditHasBeenSaved(Window->FunctionEdit);
  274.         SetTextEditAutoIndent(Window->FunctionEdit,True);
  275.  
  276.         Window->NumFramesEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  277.             GetScreenFont(),9,FRAMEEDITX,FRAMEEDITY,FRAMEEDITWIDTH,FRAMEEDITHEIGHT);
  278.         if (Window->NumFramesEdit == NIL)
  279.             {
  280.              FailurePoint7:
  281.                 goto FailurePoint6;
  282.             }
  283.         StringTemp = IntegerToString(WaveTableObjectEntriesPerTable(WaveTableObject));
  284.         if (StringTemp == NIL)
  285.             {
  286.              FailurePoint8:
  287.                 DisposeTextEdit(Window->NumFramesEdit);
  288.                 goto FailurePoint7;
  289.             }
  290.         TextEditNewRawData(Window->NumFramesEdit,StringTemp,"\x0a");
  291.         ReleasePtr(StringTemp);
  292.         TextEditHasBeenSaved(Window->NumFramesEdit);
  293.  
  294.         Window->NumTablesEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  295.             GetScreenFont(),9,TABLESEDITX,TABLESEDITY,TABLESEDITWIDTH,TABLESEDITHEIGHT);
  296.         if (Window->NumTablesEdit == NIL)
  297.             {
  298.              FailurePoint9:
  299.                 goto FailurePoint8;
  300.             }
  301.         StringTemp = IntegerToString(WaveTableObjectGetNumTables(WaveTableObject));
  302.         if (StringTemp == NIL)
  303.             {
  304.              FailurePoint10:
  305.                 DisposeTextEdit(Window->NumTablesEdit);
  306.                 goto FailurePoint9;
  307.             }
  308.         TextEditNewRawData(Window->NumTablesEdit,StringTemp,"\x0a");
  309.         ReleasePtr(StringTemp);
  310.         TextEditHasBeenSaved(Window->NumTablesEdit);
  311.  
  312.         Window->TestAttackDuration = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  313.             GetScreenFont(),9,TESTATTACKDURATIONX,TESTATTACKDURATIONY,TESTATTACKDURATIONWIDTH,
  314.             TESTATTACKDURATIONHEIGHT);
  315.         if (Window->TestAttackDuration == NIL)
  316.             {
  317.              FailurePoint11:
  318.                 goto FailurePoint10;
  319.             }
  320.         StringTemp = LongDoubleToString(WaveTableObjectGetTestAttack(WaveTableObject),
  321.             6,1e-4,1e6);
  322.         if (StringTemp == NIL)
  323.             {
  324.              FailurePoint12:
  325.                 DisposeTextEdit(Window->TestAttackDuration);
  326.                 goto FailurePoint11;
  327.             }
  328.         TextEditNewRawData(Window->TestAttackDuration,StringTemp,"\x0a");
  329.         ReleasePtr(StringTemp);
  330.  
  331.         Window->TestDecayDuration = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  332.             GetScreenFont(),9,TESTDECAYDURATIONX,TESTDECAYDURATIONY,TESTDECAYDURATIONWIDTH,
  333.             TESTDECAYDURATIONHEIGHT);
  334.         if (Window->TestDecayDuration == NIL)
  335.             {
  336.              FailurePoint13:
  337.                 goto FailurePoint12;
  338.             }
  339.         StringTemp = LongDoubleToString(WaveTableObjectGetTestDecay(WaveTableObject),
  340.             6,1e-4,1e6);
  341.         if (StringTemp == NIL)
  342.             {
  343.              FailurePoint14:
  344.                 DisposeTextEdit(Window->TestDecayDuration);
  345.                 goto FailurePoint13;
  346.             }
  347.         TextEditNewRawData(Window->TestDecayDuration,StringTemp,"\x0a");
  348.         ReleasePtr(StringTemp);
  349.  
  350.         Window->Bits8Button = NewIconButtonPreparedBitmaps(Window->ScreenID,BITS8BUTTONX,
  351.             BITS8BUTTONY,BITS8BUTTONWIDTH,BITS8BUTTONHEIGHT,Bits8Unselected,Bits8MouseDown,
  352.             Bits8Selected,Bits8Selected,eIconRadioMode);
  353.         if (Window->Bits8Button == NIL)
  354.             {
  355.              FailurePoint15:
  356.                 goto FailurePoint14;
  357.             }
  358.  
  359.         Window->Bits16Button = NewIconButtonPreparedBitmaps(Window->ScreenID,BITS16BUTTONX,
  360.             BITS16BUTTONY,BITS16BUTTONWIDTH,BITS16BUTTONHEIGHT,Bits16Unselected,
  361.             Bits16MouseDown,Bits16Selected,Bits16Selected,eIconRadioMode);
  362.         if (Window->Bits16Button == NIL)
  363.             {
  364.              FailurePoint16:
  365.                 DisposeIconButton(Window->Bits8Button);
  366.                 goto FailurePoint15;
  367.             }
  368.  
  369.         switch (WaveTableObjectGetNumBits(WaveTableObject))
  370.             {
  371.                 default:
  372.                     EXECUTE(PRERR(ForceAbort,"NewWaveTableWindow:  bad number of bits"));
  373.                     break;
  374.                 case eSample8bit:
  375.                     SetIconButtonState(Window->Bits8Button,True);
  376.                     break;
  377.                 case eSample16bit:
  378.                     SetIconButtonState(Window->Bits16Button,True);
  379.                     break;
  380.             }
  381.  
  382.         Window->TestButton = NewSimpleButton(Window->ScreenID,"Test",
  383.             TESTBUTTONX,TESTBUTTONY,TESTBUTTONWIDTH,TESTBUTTONHEIGHT);
  384.         if (Window->TestButton == NIL)
  385.             {
  386.              FailurePoint17:
  387.                 DisposeIconButton(Window->Bits16Button);
  388.                 goto FailurePoint16;
  389.             }
  390.  
  391.         Window->TableScroll = NewScrollBar(Window->ScreenID,eHScrollBar,
  392.             WAVEFORMVIEWX,TABLESCROLLY(WinHeight),WAVEFORMVIEWWIDTH(WinWidth));
  393.         if (Window->TableScroll == NIL)
  394.             {
  395.              FailurePoint18:
  396.                 DisposeSimpleButton(Window->TestButton);
  397.                 goto FailurePoint17;
  398.             }
  399.         Window->CurrentlyVisibleTable = 0;
  400.  
  401.         Window->WaveTableData = NewWaveTableStorDisp(WaveTableStorageNumBits(WaveData),
  402.             WaveTableStorageNumFramesPerTable(WaveData));
  403.         if (Window->WaveTableData == NIL)
  404.             {
  405.              FailurePoint19:
  406.                 DisposeScrollBar(Window->TableScroll);
  407.                 goto FailurePoint18;
  408.             }
  409.         Limit = WaveTableStorageNumTables(WaveData);
  410.         for (Scan = 0; Scan < Limit; Scan += 1)
  411.             {
  412.                 long                            Index;
  413.                 long                            IndexLimit;
  414.  
  415.                 if (!WaveTableStorDispAppendEntry(Window->WaveTableData))
  416.                     {
  417.                      FailurePoint20:
  418.                         DisposeWaveTableStorDisp(Window->WaveTableData);
  419.                         goto FailurePoint19;
  420.                     }
  421.                 IndexLimit = WaveTableStorageNumFramesPerTable(WaveData);
  422.                 for (Index = 0; Index < IndexLimit; Index += 1)
  423.                     {
  424.                         WaveTableStorDispSetFrame(Window->WaveTableData,Scan,Index,
  425.                             WaveTableStorageGetFrame(WaveData,Scan,Index));
  426.                     }
  427.             }
  428.  
  429.         Window->MyGenericWindow = CheckInNewWindow(Window->ScreenID,Window,
  430.             (void (*)(void*,MyBoolean,OrdType,OrdType,ModifierFlags))&WaveTableWindowDoIdle,
  431.             (void (*)(void*))&WaveTableWindowBecomeActive,
  432.             (void (*)(void*))&WaveTableWindowBecomeInactive,
  433.             (void (*)(void*))&WaveTableWindowJustResized,
  434.             (void (*)(OrdType,OrdType,ModifierFlags,void*))&WaveTableWindowDoMouseDown,
  435.             (void (*)(unsigned char,ModifierFlags,void*))&WaveTableWindowDoKeyDown,
  436.             (void (*)(void*))&WaveTableWindowClose,
  437.             (void (*)(void*))&WaveTableWindowMenuSetup,
  438.             (void (*)(void*,MenuItemType*))&WaveTableWindowDoMenuCommand);
  439.         if (Window->MyGenericWindow == NIL)
  440.             {
  441.              FailurePoint21:
  442.                 goto FailurePoint20;
  443.             }
  444.  
  445.         Window->TestFrequency = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  446.             GetScreenFont(),9,TESTFREQUENCYX,TESTFREQUENCYY,TESTFREQUENCYWIDTH,
  447.             TESTFREQUENCYHEIGHT);
  448.         if (Window->TestFrequency == NIL)
  449.             {
  450.              FailurePoint22:
  451.                 CheckOutDyingWindow(Window->MyGenericWindow);
  452.                 goto FailurePoint21;
  453.             }
  454.         StringTemp = LongDoubleToString(WaveTableObjectGetTestPitch(WaveTableObject),
  455.             13,1e-4,1e6);
  456.         if (StringTemp == NIL)
  457.             {
  458.              FailurePoint23:
  459.                 DisposeTextEdit(Window->TestFrequency);
  460.                 goto FailurePoint22;
  461.             }
  462.         TextEditNewRawData(Window->TestFrequency,StringTemp,"\x0a");
  463.         ReleasePtr(StringTemp);
  464.  
  465.         Window->TestSamplingRate = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  466.             GetScreenFont(),9,TESTSAMPLINGRATEX,TESTSAMPLINGRATEY,TESTSAMPLINGRATEWIDTH,
  467.             TESTSAMPLINGRATEHEIGHT);
  468.         if (Window->TestSamplingRate == NIL)
  469.             {
  470.              FailurePoint24:
  471.                 goto FailurePoint23;
  472.             }
  473.         StringTemp = IntegerToString(WaveTableObjectGetTestSamplingRate(WaveTableObject));
  474.         if (StringTemp == NIL)
  475.             {
  476.              FailurePoint25:
  477.                 DisposeTextEdit(Window->TestSamplingRate);
  478.                 goto FailurePoint24;
  479.             }
  480.         TextEditNewRawData(Window->TestSamplingRate,StringTemp,"\x0a");
  481.         ReleasePtr(StringTemp);
  482.  
  483.         Window->MyMenuItem = MakeNewMenuItem(mmWindowMenu,"x",0);
  484.         if (Window->MyMenuItem == NIL)
  485.             {
  486.              FailurePoint26:
  487.                 goto FailurePoint25;
  488.             }
  489.         if (!RegisterWindowMenuItem(Window->MyMenuItem,(void (*)(void*))&ActivateThisWindow,
  490.             Window->ScreenID))
  491.             {
  492.              FailurePoint27:
  493.                 KillMenuItem(Window->MyMenuItem);
  494.                 goto FailurePoint26;
  495.             }
  496.  
  497.         Window->WaveDataModified = False;
  498.         Window->ActiveTextEdit = Window->FunctionEdit;
  499.         Window->UndoBackupWaveTable = NIL;
  500.         WaveTableWindowResetTitlebar(Window);
  501.         WaveTableWindowUpdateScrollBar(Window);
  502.  
  503.         return Window;
  504.     }
  505.  
  506.  
  507. /* write back modified data and dispose of the wave table window */
  508. void                                DisposeWaveTableWindow(WaveTableWindowRec* Window)
  509.     {
  510.         CheckPtrExistence(Window);
  511.  
  512.         /* save data */
  513.         if (!WaveTableWindowWritebackModifiedData(Window))
  514.             {
  515.                 /* failed -- now what? */
  516.             }
  517.  
  518.         WaveTableObjectClosingWindowNotify(Window->WaveTableObject,
  519.             GetWindowXStart(Window->ScreenID),GetWindowYStart(Window->ScreenID),
  520.             GetWindowWidth(Window->ScreenID),GetWindowHeight(Window->ScreenID));
  521.         DeregisterWindowMenuItem(Window->MyMenuItem);
  522.         KillMenuItem(Window->MyMenuItem);
  523.         CheckOutDyingWindow(Window->MyGenericWindow);
  524.         DisposeWaveTableStorDisp(Window->WaveTableData);
  525.         if (Window->UndoBackupWaveTable != NIL)
  526.             {
  527.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  528.             }
  529.         DisposeScrollBar(Window->TableScroll);
  530.         DisposeIconButton(Window->Bits16Button);
  531.         DisposeIconButton(Window->Bits8Button);
  532.         DisposeTextEdit(Window->NameEdit);
  533.         DisposeTextEdit(Window->FunctionEdit);
  534.         DisposeTextEdit(Window->NumFramesEdit);
  535.         DisposeTextEdit(Window->NumTablesEdit);
  536.         DisposeTextEdit(Window->TestAttackDuration);
  537.         DisposeTextEdit(Window->TestDecayDuration);
  538.         DisposeTextEdit(Window->TestFrequency);
  539.         DisposeTextEdit(Window->TestSamplingRate);
  540.         DisposeSimpleButton(Window->TestButton);
  541.         KillWindow(Window->ScreenID);
  542.         ReleasePtr((char*)Window);
  543.     }
  544.  
  545.  
  546. /* return True if the data has been modified since the last time the file was saved */
  547. MyBoolean                        HasWaveTableWindowBeenModified(WaveTableWindowRec* Window)
  548.     {
  549.         CheckPtrExistence(Window);
  550.         return Window->WaveDataModified
  551.             || TextEditDoesItNeedToBeSaved(Window->NameEdit)
  552.             || TextEditDoesItNeedToBeSaved(Window->FunctionEdit)
  553.             || TextEditDoesItNeedToBeSaved(Window->TestAttackDuration)
  554.             || TextEditDoesItNeedToBeSaved(Window->TestDecayDuration)
  555.             || TextEditDoesItNeedToBeSaved(Window->TestFrequency)
  556.             || TextEditDoesItNeedToBeSaved(Window->TestSamplingRate);
  557.     }
  558.  
  559.  
  560. /* bring the window to the top and give it the focus */
  561. void                                WaveTableWindowBringToTop(WaveTableWindowRec* Window)
  562.     {
  563.         CheckPtrExistence(Window);
  564.         ActivateThisWindow(Window->ScreenID);
  565.     }
  566.  
  567.  
  568. void                                WaveTableWindowDoIdle(WaveTableWindowRec* Window,
  569.                                             MyBoolean CheckCursorFlag, OrdType XLoc, OrdType YLoc,
  570.                                             ModifierFlags Modifiers)
  571.     {
  572.         CheckPtrExistence(Window);
  573.         if (Window->ActiveTextEdit != NIL)
  574.             {
  575.                 TextEditUpdateCursor(Window->ActiveTextEdit);
  576.             }
  577.         if (CheckCursorFlag)
  578.             {
  579.                 if (TextEditIBeamTest(Window->NameEdit,XLoc,YLoc)
  580.                     || TextEditIBeamTest(Window->FunctionEdit,XLoc,YLoc)
  581.                     || TextEditIBeamTest(Window->NumFramesEdit,XLoc,YLoc)
  582.                     || TextEditIBeamTest(Window->NumTablesEdit,XLoc,YLoc)
  583.                     || TextEditIBeamTest(Window->TestAttackDuration,XLoc,YLoc)
  584.                     || TextEditIBeamTest(Window->TestDecayDuration,XLoc,YLoc)
  585.                     || TextEditIBeamTest(Window->TestFrequency,XLoc,YLoc)
  586.                     || TextEditIBeamTest(Window->TestSamplingRate,XLoc,YLoc))
  587.                     {
  588.                         SetIBeamCursor();
  589.                     }
  590.                 else if ((XLoc >= WAVEFORMVIEWX) && (YLoc >= WAVEFORMVIEWY)
  591.                     && (XLoc < WAVEFORMVIEWX + WAVEFORMVIEWWIDTH(GetWindowWidth(Window->ScreenID)))
  592.                     && (YLoc < WAVEFORMVIEWY
  593.                     + WAVEFORMVIEWHEIGHT(GetWindowHeight(Window->ScreenID)) - 15))
  594.                     {
  595.                         SetSampleInsertionCursor();
  596.                     }
  597.                 else
  598.                     {
  599.                         SetArrowCursor();
  600.                     }
  601.             }
  602.     }
  603.  
  604.  
  605. void                                WaveTableWindowBecomeActive(WaveTableWindowRec* Window)
  606.     {
  607.         OrdType                        XSize;
  608.         OrdType                        YSize;
  609.  
  610.         CheckPtrExistence(Window);
  611.         if (Window->ActiveTextEdit != NIL)
  612.             {
  613.                 EnableTextEditSelection(Window->ActiveTextEdit);
  614.             }
  615.         EnableScrollBar(Window->TableScroll);
  616.         XSize = GetWindowWidth(Window->ScreenID);
  617.         YSize = GetWindowHeight(Window->ScreenID);
  618.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  619.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(True/*enablegrowicon*/));
  620.     }
  621.  
  622.  
  623. void                                WaveTableWindowBecomeInactive(WaveTableWindowRec* Window)
  624.     {
  625.         OrdType                        XSize;
  626.         OrdType                        YSize;
  627.  
  628.         CheckPtrExistence(Window);
  629.         if (Window->ActiveTextEdit != NIL)
  630.             {
  631.                 DisableTextEditSelection(Window->ActiveTextEdit);
  632.             }
  633.         DisableScrollBar(Window->TableScroll);
  634.         XSize = GetWindowWidth(Window->ScreenID);
  635.         YSize = GetWindowHeight(Window->ScreenID);
  636.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  637.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(False/*disablegrowicon*/));
  638.     }
  639.  
  640.  
  641. void                                WaveTableWindowJustResized(WaveTableWindowRec* Window)
  642.     {
  643.         OrdType                        XSize;
  644.         OrdType                        YSize;
  645.  
  646.         CheckPtrExistence(Window);
  647.         XSize = GetWindowWidth(Window->ScreenID);
  648.         YSize = GetWindowHeight(Window->ScreenID);
  649.         SetClipRect(Window->ScreenID,0,0,XSize,YSize);
  650.         DrawBoxErase(Window->ScreenID,0,0,XSize,YSize);
  651.  
  652.         SetTextEditPosition(Window->FunctionEdit,EXPRESSIONEDITX,EXPRESSIONEDITY(YSize),
  653.             EXPRESSIONEDITWIDTH(XSize),EXPRESSIONEDITHEIGHT);
  654.         SetScrollLocation(Window->TableScroll,WAVEFORMVIEWX,TABLESCROLLY(YSize),
  655.             WAVEFORMVIEWWIDTH(XSize));
  656.     }
  657.  
  658.  
  659. static void                    WaveTableWindowScrollHook(long Parameter, ScrollType How,
  660.                                             WaveTableWindowRec* Window)
  661.     {
  662.         CheckPtrExistence(Window);
  663.         switch (How)
  664.             {
  665.                 case eScrollToPosition:
  666.                     Window->CurrentlyVisibleTable = Parameter;
  667.                     WaveTableWindowUpdateScrollBar(Window);
  668.                     WaveTableWindowRedrawTable(Window);
  669.                     break;
  670.                 case eScrollPageMinus:
  671.                     Window->CurrentlyVisibleTable -= PAGEINCREMENT;
  672.                     if (Window->CurrentlyVisibleTable < 0)
  673.                         {
  674.                             Window->CurrentlyVisibleTable = 0;
  675.                         }
  676.                     WaveTableWindowUpdateScrollBar(Window);
  677.                     WaveTableWindowRedrawTable(Window);
  678.                     break;
  679.                 case eScrollPagePlus:
  680.                     Window->CurrentlyVisibleTable += PAGEINCREMENT;
  681.                     if (Window->CurrentlyVisibleTable > WaveTableWindowGetNumTables(Window) - 1)
  682.                         {
  683.                             Window->CurrentlyVisibleTable = WaveTableWindowGetNumTables(Window) - 1;
  684.                         }
  685.                     if (Window->CurrentlyVisibleTable < 0)
  686.                         {
  687.                             /* just in case there are 0 tables -- this makes index become -1 */
  688.                             Window->CurrentlyVisibleTable = 0;
  689.                         }
  690.                     WaveTableWindowUpdateScrollBar(Window);
  691.                     WaveTableWindowRedrawTable(Window);
  692.                     break;
  693.                 case eScrollLineMinus:
  694.                     Window->CurrentlyVisibleTable -= 1;
  695.                     if (Window->CurrentlyVisibleTable < 0)
  696.                         {
  697.                             Window->CurrentlyVisibleTable = 0;
  698.                         }
  699.                     WaveTableWindowUpdateScrollBar(Window);
  700.                     WaveTableWindowRedrawTable(Window);
  701.                     break;
  702.                 case eScrollLinePlus:
  703.                     Window->CurrentlyVisibleTable += 1;
  704.                     if (Window->CurrentlyVisibleTable > WaveTableWindowGetNumTables(Window) - 1)
  705.                         {
  706.                             Window->CurrentlyVisibleTable = WaveTableWindowGetNumTables(Window) - 1;
  707.                         }
  708.                     if (Window->CurrentlyVisibleTable < 0)
  709.                         {
  710.                             /* just in case there are 0 tables -- this makes index become -1 */
  711.                             Window->CurrentlyVisibleTable = 0;
  712.                         }
  713.                     WaveTableWindowUpdateScrollBar(Window);
  714.                     WaveTableWindowRedrawTable(Window);
  715.                     break;
  716.                 default:
  717.                     EXECUTE(PRERR(AllowResume,"WaveTableWindowScrollHook:  Unknown scroll opcode"));
  718.                     break;
  719.             }
  720.     }
  721.  
  722.  
  723. #define SOUNDBUFFERLENGTHBYTES (16384)
  724. #define NUMSOUNDBUFFERS (4)
  725. static void                    WaveTablePlayIt(WaveTableWindowRec* Window)
  726.     {
  727.         WaveTableStorageRec*        NewWaveTable;
  728.         long                                        Limit;
  729.         long                                        Scan;
  730.         SoundOutputNumBits            SoundChannelBits;
  731.         void**                                    ReferenceArray;
  732.         unsigned long                        WaveformIndex;
  733.         unsigned long                        WaveformIncrementor;
  734.         unsigned long                        WaveformMask;
  735.         long                                        NumberOfIterationsAttack;
  736.         long                                        NumberOfIterationsDecay;
  737.         long                                        PlaybackSamplingRate;
  738.         char*                                        OutputBuffer;
  739.         long                                        OutputIndex;
  740.  
  741.         /* create the table */
  742.         NewWaveTable = NewWaveTableStorage(WaveTableStorDispNumBits(Window->WaveTableData),
  743.             WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  744.         if (NewWaveTable == NIL)
  745.             {
  746.                 AlertHalt("There is not enough memory available to play the sample.",NIL);
  747.              FailurePoint1:
  748.                 return;
  749.             }
  750.  
  751.         /* fill in the table */
  752.         Limit = WaveTableStorDispNumTables(Window->WaveTableData);
  753.         for (Scan = 0; Scan < Limit; Scan += 1)
  754.             {
  755.                 long                            Index;
  756.                 long                            IndexLimit;
  757.  
  758.                 if (!WaveTableStorageAppendEntry(NewWaveTable))
  759.                     {
  760.                         AlertHalt("There is not enough memory available to play the sample.",NIL);
  761.                      FailurePoint2:
  762.                         DisposeWaveTableStorage(NewWaveTable);
  763.                         goto FailurePoint1;
  764.                     }
  765.                 IndexLimit = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  766.                 for (Index = 0; Index < IndexLimit; Index += 1)
  767.                     {
  768.                         WaveTableStorageSetFrame(NewWaveTable,Scan,Index,
  769.                             WaveTableStorDispGetFrame(Window->WaveTableData,Scan,Index));
  770.                     }
  771.             }
  772.  
  773.         /* fill in the buffer */
  774.         ReferenceArray = (void**)AllocPtrCanFail(sizeof(void*)
  775.             * WaveTableStorageNumTables(NewWaveTable),"WaveTablePlayIt:  ReferenceArray");
  776.         if (ReferenceArray == NIL)
  777.             {
  778.                 AlertHalt("There is not enough memory available to play the sample.",NIL);
  779.              FailurePoint3:
  780.                 goto FailurePoint2;
  781.             }
  782.         for (Scan = 0; Scan < WaveTableStorageNumTables(NewWaveTable); Scan += 1)
  783.             {
  784.                 ReferenceArray[Scan] = WaveTableStorageGetTable(NewWaveTable,Scan);
  785.             }
  786.  
  787.         /* how many bits should be used for playback */
  788.         switch (WaveTableStorDispNumBits(Window->WaveTableData))
  789.             {
  790.                 default:
  791.                     EXECUTE(PRERR(ForceAbort,"WaveTablePlayIt:  bad number of bits"));
  792.                     break;
  793.                 case eSample16bit:
  794.                     SoundChannelBits = e16bit;
  795.                     break;
  796.                 case eSample8bit:
  797.                     SoundChannelBits = e8bit;
  798.                     break;
  799.             }
  800.  
  801.         /* playback at what sampling rate */
  802.         PlaybackSamplingRate = WaveTableWindowGetTestSamplingRate(Window);
  803.         if (PlaybackSamplingRate < MINSAMPLINGRATE)
  804.             {
  805.                 PlaybackSamplingRate = MINSAMPLINGRATE;
  806.             }
  807.         if (PlaybackSamplingRate > MAXSAMPLINGRATE)
  808.             {
  809.                 PlaybackSamplingRate = MAXSAMPLINGRATE;
  810.             }
  811.  
  812.         /* this is the initial index into the wave table */
  813.         WaveformIndex = 0;
  814.  
  815.         /* this is the 16.16 bit fixed point number used to increment the index */
  816.         /* into the wave table */
  817.         WaveformIncrementor = WaveTableWindowGetNumFramesPerTable(Window)
  818.             * WaveTableWindowGetPitch(Window) / PlaybackSamplingRate * 65536;
  819.  
  820.         /* this is used to mask off all garbage bits from the index when */
  821.         /* looking values up in the wave table */
  822.         WaveformMask = WaveTableWindowGetNumFramesPerTable(Window) - 1;
  823.  
  824.         /* the number of times each wave slice has to be used */
  825.         NumberOfIterationsAttack = WaveTableWindowGetAscendingDuration(Window)
  826.             / (double)Limit * PlaybackSamplingRate;
  827.         NumberOfIterationsDecay = WaveTableWindowGetDescendingDuration(Window)
  828.             / (double)Limit * PlaybackSamplingRate;
  829.  
  830.         if (!OpenSoundChannel(PlaybackSamplingRate,eMono,SoundChannelBits,
  831.             SOUNDBUFFERLENGTHBYTES,NUMSOUNDBUFFERS,NUMSOUNDBUFFERS))
  832.             {
  833.                 AlertHalt("Unable top open the sound device.",NIL);
  834.              FailurePoint4:
  835.                 ReleasePtr((char*)ReferenceArray);
  836.                 goto FailurePoint3;
  837.             }
  838.         OutputIndex = 0;
  839.         do
  840.             {
  841.                 OutputBuffer = CheckOutSoundBuffer();
  842.             } while (OutputBuffer == NIL);
  843.  
  844.         if (SoundChannelBits == e16bit)
  845.             {
  846.                 for (Scan = 0; Scan < Limit; Scan += 1)
  847.                     {
  848.                         signed short*                    Buffer = (signed short*)(ReferenceArray[Scan]);
  849.                         long                                    Index;
  850.  
  851.                         for (Index = 0; Index < NumberOfIterationsAttack; Index += 1)
  852.                             {
  853.                                 unsigned long                    SampleReference;
  854.                                 signed short                    Left;
  855.                                 signed short                    Right;
  856.                                 signed long                        Fraction;
  857.  
  858.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  859.                                 Left = Buffer[SampleReference];
  860.                                 Right = Buffer[SampleReference + 1];
  861.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  862.                                 WaveformIndex += WaveformIncrementor;
  863.                                 ((short*)OutputBuffer)[OutputIndex] = ((Left * (0x8000 - Fraction)
  864.                                     + Right * Fraction) >> 15) >> 1;
  865.                                 OutputIndex += 1;
  866.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(short))
  867.                                     {
  868.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(short),
  869.                                             NIL,NIL);
  870.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  871.                                             {
  872.                                                 goto EscapePoint;
  873.                                             }
  874.                                         do
  875.                                             {
  876.                                                 OutputBuffer = CheckOutSoundBuffer();
  877.                                             } while (OutputBuffer == NIL);
  878.                                         OutputIndex = 0;
  879.                                     }
  880.                             }
  881.                     }
  882.             }
  883.          else
  884.             {
  885.                 for (Scan = 0; Scan < Limit; Scan += 1)
  886.                     {
  887.                         signed char*                    Buffer = (signed char*)(ReferenceArray[Scan]);
  888.                         long                                    Index;
  889.  
  890.                         for (Index = 0; Index < NumberOfIterationsAttack; Index += 1)
  891.                             {
  892.                                 unsigned long                    SampleReference;
  893.                                 signed short                    Left;
  894.                                 signed short                    Right;
  895.                                 signed long                        Fraction;
  896.  
  897.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  898.                                 Left = Buffer[SampleReference];
  899.                                 Right = Buffer[SampleReference + 1];
  900.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  901.                                 WaveformIndex += WaveformIncrementor;
  902.                                 ((char*)OutputBuffer)[OutputIndex] = ((Left * (0x8000 - Fraction)
  903.                                     + Right * Fraction) >> 15) >> 1;
  904.                                 OutputIndex += 1;
  905.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(char))
  906.                                     {
  907.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(char),
  908.                                             NIL,NIL);
  909.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  910.                                             {
  911.                                                 goto EscapePoint;
  912.                                             }
  913.                                         do
  914.                                             {
  915.                                                 OutputBuffer = CheckOutSoundBuffer();
  916.                                             } while (OutputBuffer == NIL);
  917.                                         OutputIndex = 0;
  918.                                     }
  919.                             }
  920.                     }
  921.             }
  922.  
  923.         if (SoundChannelBits == e16bit)
  924.             {
  925.                 for (Scan = Limit - 1; Scan >= 0; Scan -= 1)
  926.                     {
  927.                         signed short*                    Buffer = (signed short*)(ReferenceArray[Scan]);
  928.                         long                                    Index;
  929.  
  930.                         for (Index = 0; Index < NumberOfIterationsDecay; Index += 1)
  931.                             {
  932.                                 unsigned long                    SampleReference;
  933.                                 signed short                    Left;
  934.                                 signed short                    Right;
  935.                                 signed long                        Fraction;
  936.  
  937.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  938.                                 Left = Buffer[SampleReference];
  939.                                 Right = Buffer[SampleReference + 1];
  940.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  941.                                 WaveformIndex += WaveformIncrementor;
  942.                                 ((short*)OutputBuffer)[OutputIndex] = ((Left * (0x8000 - Fraction)
  943.                                     + Right * Fraction) >> 15) >> 1;
  944.                                 OutputIndex += 1;
  945.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(short))
  946.                                     {
  947.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(short),
  948.                                             NIL,NIL);
  949.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  950.                                             {
  951.                                                 goto EscapePoint;
  952.                                             }
  953.                                         do
  954.                                             {
  955.                                                 OutputBuffer = CheckOutSoundBuffer();
  956.                                             } while (OutputBuffer == NIL);
  957.                                         OutputIndex = 0;
  958.                                     }
  959.                             }
  960.                     }
  961.                 SubmitBuffer(OutputBuffer,OutputIndex / sizeof(short),NIL,NIL);
  962.             }
  963.          else
  964.             {
  965.                 for (Scan = Limit - 1; Scan >= 0; Scan -= 1)
  966.                     {
  967.                         signed char*                    Buffer = (signed char*)(ReferenceArray[Scan]);
  968.                         long                                    Index;
  969.  
  970.                         for (Index = 0; Index < NumberOfIterationsDecay; Index += 1)
  971.                             {
  972.                                 unsigned long                    SampleReference;
  973.                                 signed short                    Left;
  974.                                 signed short                    Right;
  975.                                 signed long                        Fraction;
  976.  
  977.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  978.                                 Left = Buffer[SampleReference];
  979.                                 Right = Buffer[SampleReference + 1];
  980.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  981.                                 WaveformIndex += WaveformIncrementor;
  982.                                 ((char*)OutputBuffer)[OutputIndex] = ((Left * (0x8000 - Fraction)
  983.                                     + Right * Fraction) >> 15) >> 1;
  984.                                 OutputIndex += 1;
  985.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(char))
  986.                                     {
  987.                                         SubmitBuffer(OutputBuffer,SOUNDBUFFERLENGTHBYTES / sizeof(char),
  988.                                             NIL,NIL);
  989.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  990.                                             {
  991.                                                 goto EscapePoint;
  992.                                             }
  993.                                         do
  994.                                             {
  995.                                                 OutputBuffer = CheckOutSoundBuffer();
  996.                                             } while (OutputBuffer == NIL);
  997.                                         OutputIndex = 0;
  998.                                     }
  999.                             }
  1000.                     }
  1001.                 SubmitBuffer(OutputBuffer,OutputIndex / sizeof(char),NIL,NIL);
  1002.             }
  1003.  
  1004.      EscapePoint:
  1005.         CloseSoundChannel(NIL,NIL);
  1006.         ReleasePtr((char*)ReferenceArray);
  1007.         DisposeWaveTableStorage(NewWaveTable);
  1008.     }
  1009.  
  1010.  
  1011. void                                WaveTableWindowDoMouseDown(OrdType XLoc, OrdType YLoc,
  1012.                                             ModifierFlags Modifiers, WaveTableWindowRec* Window)
  1013.     {
  1014.         CheckPtrExistence(Window);
  1015.         if ((XLoc >= GetWindowWidth(Window->ScreenID) - 15)
  1016.             && (XLoc < GetWindowWidth(Window->ScreenID))
  1017.             && (YLoc >= GetWindowHeight(Window->ScreenID) - 15)
  1018.             && (YLoc < GetWindowHeight(Window->ScreenID)))
  1019.             {
  1020.                 UserGrowWindow(Window->ScreenID,XLoc,YLoc);
  1021.                 WaveTableWindowJustResized(Window);
  1022.             }
  1023.         else if (TextEditHitTest(Window->NameEdit,XLoc,YLoc))
  1024.             {
  1025.                 if (Window->ActiveTextEdit != Window->NameEdit)
  1026.                     {
  1027.                         if (Window->ActiveTextEdit != NIL)
  1028.                             {
  1029.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1030.                             }
  1031.                         Window->ActiveTextEdit = Window->NameEdit;
  1032.                         EnableTextEditSelection(Window->NameEdit);
  1033.                     }
  1034.                 TextEditDoMouseDown(Window->NameEdit,XLoc,YLoc,Modifiers);
  1035.             }
  1036.         else if (TextEditHitTest(Window->FunctionEdit,XLoc,YLoc))
  1037.             {
  1038.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1039.                     {
  1040.                         if (Window->ActiveTextEdit != NIL)
  1041.                             {
  1042.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1043.                             }
  1044.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1045.                         EnableTextEditSelection(Window->FunctionEdit);
  1046.                     }
  1047.                 TextEditDoMouseDown(Window->FunctionEdit,XLoc,YLoc,Modifiers);
  1048.             }
  1049.         else if (TextEditHitTest(Window->TestAttackDuration,XLoc,YLoc))
  1050.             {
  1051.                 if (Window->ActiveTextEdit != Window->TestAttackDuration)
  1052.                     {
  1053.                         if (Window->ActiveTextEdit != NIL)
  1054.                             {
  1055.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1056.                             }
  1057.                         Window->ActiveTextEdit = Window->TestAttackDuration;
  1058.                         EnableTextEditSelection(Window->TestAttackDuration);
  1059.                     }
  1060.                 TextEditDoMouseDown(Window->TestAttackDuration,XLoc,YLoc,Modifiers);
  1061.             }
  1062.         else if (TextEditHitTest(Window->TestDecayDuration,XLoc,YLoc))
  1063.             {
  1064.                 if (Window->ActiveTextEdit != Window->TestDecayDuration)
  1065.                     {
  1066.                         if (Window->ActiveTextEdit != NIL)
  1067.                             {
  1068.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1069.                             }
  1070.                         Window->ActiveTextEdit = Window->TestDecayDuration;
  1071.                         EnableTextEditSelection(Window->TestDecayDuration);
  1072.                     }
  1073.                 TextEditDoMouseDown(Window->TestDecayDuration,XLoc,YLoc,Modifiers);
  1074.             }
  1075.         else if (TextEditHitTest(Window->TestFrequency,XLoc,YLoc))
  1076.             {
  1077.                 if (Window->ActiveTextEdit != Window->TestFrequency)
  1078.                     {
  1079.                         if (Window->ActiveTextEdit != NIL)
  1080.                             {
  1081.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1082.                             }
  1083.                         Window->ActiveTextEdit = Window->TestFrequency;
  1084.                         EnableTextEditSelection(Window->TestFrequency);
  1085.                     }
  1086.                 TextEditDoMouseDown(Window->TestFrequency,XLoc,YLoc,Modifiers);
  1087.             }
  1088.         else if (TextEditHitTest(Window->TestSamplingRate,XLoc,YLoc))
  1089.             {
  1090.                 if (Window->ActiveTextEdit != Window->TestSamplingRate)
  1091.                     {
  1092.                         if (Window->ActiveTextEdit != NIL)
  1093.                             {
  1094.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1095.                             }
  1096.                         Window->ActiveTextEdit = Window->TestSamplingRate;
  1097.                         EnableTextEditSelection(Window->TestSamplingRate);
  1098.                     }
  1099.                 TextEditDoMouseDown(Window->TestSamplingRate,XLoc,YLoc,Modifiers);
  1100.             }
  1101.         else if (TextEditHitTest(Window->NumFramesEdit,XLoc,YLoc))
  1102.             {
  1103.                 WaveTableWindowSetNewNumFrames(Window);
  1104.             }
  1105.         else if (TextEditHitTest(Window->NumTablesEdit,XLoc,YLoc))
  1106.             {
  1107.                 WaveTableWindowSetNewNumTables(Window);
  1108.             }
  1109.         else if (IconButtonHitTest(Window->Bits8Button,XLoc,YLoc))
  1110.             {
  1111.                 if (IconButtonMouseDown(Window->Bits8Button,XLoc,YLoc,NIL,NIL))
  1112.                     {
  1113.                         SetWaveTableStorDispNumBits(Window->WaveTableData,eSample8bit);
  1114.                         SetIconButtonState(Window->Bits16Button,False);
  1115.                         Window->WaveDataModified = True;
  1116.                     }
  1117.             }
  1118.         else if (IconButtonHitTest(Window->Bits16Button,XLoc,YLoc))
  1119.             {
  1120.                 if (IconButtonMouseDown(Window->Bits16Button,XLoc,YLoc,NIL,NIL))
  1121.                     {
  1122.                         SetWaveTableStorDispNumBits(Window->WaveTableData,eSample16bit);
  1123.                         SetIconButtonState(Window->Bits8Button,False);
  1124.                         Window->WaveDataModified = True;
  1125.                     }
  1126.             }
  1127.         else if (ScrollHitTest(Window->TableScroll,XLoc,YLoc))
  1128.             {
  1129.                 ScrollHitProc(Window->TableScroll,CheckModifiers(),XLoc,YLoc,Window,
  1130.                     (void (*)(long,ScrollType,void*))&WaveTableWindowScrollHook);
  1131.             }
  1132.         else if (SimpleButtonHitTest(Window->TestButton,XLoc,YLoc))
  1133.             {
  1134.                 if (SimpleButtonMouseDown(Window->TestButton,XLoc,YLoc,NIL,NIL))
  1135.                     {
  1136.                         WaveTablePlayIt(Window);
  1137.                     }
  1138.             }
  1139.         else
  1140.             {
  1141.                 if (Window->ActiveTextEdit != NIL)
  1142.                     {
  1143.                         DisableTextEditSelection(Window->ActiveTextEdit);
  1144.                         Window->ActiveTextEdit = NIL;
  1145.                     }
  1146.             }
  1147.     }
  1148.  
  1149.  
  1150. void                                WaveTableWindowDoKeyDown(unsigned char KeyCode,
  1151.                                             ModifierFlags Modifiers, WaveTableWindowRec* Window)
  1152.     {
  1153.         CheckPtrExistence(Window);
  1154.         if (Window->ActiveTextEdit != NIL)
  1155.             {
  1156.                 TextEditDoKeyPressed(Window->ActiveTextEdit,KeyCode,Modifiers);
  1157.             }
  1158.     }
  1159.  
  1160.  
  1161. void                                WaveTableWindowClose(WaveTableWindowRec* Window)
  1162.     {
  1163.         CheckPtrExistence(Window);
  1164.         DisposeWaveTableWindow(Window);
  1165.     }
  1166.  
  1167.  
  1168. void                                WaveTableWindowUpdator(WaveTableWindowRec* Window)
  1169.     {
  1170.         OrdType                        Height;
  1171.         OrdType                        Width;
  1172.  
  1173.         CheckPtrExistence(Window);
  1174.         Width = GetWindowWidth(Window->ScreenID);
  1175.         Height = GetWindowHeight(Window->ScreenID);
  1176.  
  1177.         TextEditFullRedraw(Window->NameEdit);
  1178.         TextEditFullRedraw(Window->FunctionEdit);
  1179.         TextEditFullRedraw(Window->NumFramesEdit);
  1180.         TextEditFullRedraw(Window->NumTablesEdit);
  1181.         TextEditFullRedraw(Window->TestAttackDuration);
  1182.         TextEditFullRedraw(Window->TestDecayDuration);
  1183.         TextEditFullRedraw(Window->TestFrequency);
  1184.         TextEditFullRedraw(Window->TestSamplingRate);
  1185.         RedrawSimpleButton(Window->TestButton);
  1186.         RedrawIconButton(Window->Bits8Button);
  1187.         RedrawIconButton(Window->Bits16Button);
  1188.         RedrawScrollBar(Window->TableScroll);
  1189.         WaveTableWindowRedrawTable(Window);
  1190.  
  1191.         SetClipRect(Window->ScreenID,0,0,Width,Height);
  1192.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Name:",5,NAMEX,NAMEY,ePlain);
  1193.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Frames:",7,FRAMEX,FRAMEY,ePlain);
  1194.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Tables:",7,TABLESX,TABLESY,ePlain);
  1195.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Attack:",12,
  1196.             TESTATTACKX,TESTATTACKY,ePlain);
  1197.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Decay:",11,
  1198.             TESTDECAYX,TESTDECAYY,ePlain);
  1199.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Freq:",10,
  1200.             TESTFREQX,TESTFREQY,ePlain);
  1201.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Smpl Rate:",15,
  1202.             TESTSAMPLX,TESTSAMPLY,ePlain);
  1203.  
  1204.         SetClipRect(Window->ScreenID,Width - 15,Height - 15,Width,Height);
  1205.         DrawBitmap(Window->ScreenID,Width - 15,Height - 15,
  1206.             GetGrowIcon(Window->MyGenericWindow == GetCurrentWindowID()));
  1207.     }
  1208.  
  1209.  
  1210. void                                WaveTableWindowMenuSetup(WaveTableWindowRec* Window)
  1211.     {
  1212.         CheckPtrExistence(Window);
  1213.         MainWindowEnableGlobalMenus(Window->MainWindow);
  1214.         EnableMenuItem(mPaste);
  1215.         ChangeItemName(mPaste,"Paste Text");
  1216.         if (Window->ActiveTextEdit != NIL)
  1217.             {
  1218.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1219.                     {
  1220.                         EnableMenuItem(mCut);
  1221.                         ChangeItemName(mCut,"Cut Text");
  1222.                         EnableMenuItem(mCopy);
  1223.                         ChangeItemName(mCopy,"Copy Text");
  1224.                         EnableMenuItem(mClear);
  1225.                         ChangeItemName(mClear,"Clear Text");
  1226.                     }
  1227.                 EnableMenuItem(mSelectAll);
  1228.                 ChangeItemName(mSelectAll,"Select All Text");
  1229.                 if (TextEditCanWeUndo(Window->ActiveTextEdit))
  1230.                     {
  1231.                         EnableMenuItem(mUndo);
  1232.                         ChangeItemName(mUndo,"Undo Text Change");
  1233.                     }
  1234.             }
  1235.          else
  1236.             {
  1237.                 if (Window->UndoBackupWaveTable != NIL)
  1238.                     {
  1239.                         EnableMenuItem(mUndo);
  1240.                         ChangeItemName(mUndo,"Undo Wave Table Edit");
  1241.                     }
  1242.             }
  1243.         EnableMenuItem(mCloseFile);
  1244.         ChangeItemName(mCloseFile,"Close Wave Table Editor");
  1245.         EnableMenuItem(mEvaluateCalc);
  1246.         EnableMenuItem(mShiftLeft);
  1247.         EnableMenuItem(mShiftRight);
  1248.         EnableMenuItem(mBalanceParens);
  1249.         ChangeItemName(mDeleteObject,"Delete Wave Table");
  1250.         EnableMenuItem(mDeleteObject);
  1251.         EnableMenuItem(mFind);
  1252.         if (PtrSize(GlobalSearchString) != 0)
  1253.             {
  1254.                 EnableMenuItem(mFindAgain);
  1255.                 if ((Window->ActiveTextEdit != NIL)
  1256.                     && TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1257.                     {
  1258.                         EnableMenuItem(mReplace);
  1259.                         EnableMenuItem(mReplaceAndFindAgain);
  1260.                     }
  1261.             }
  1262.         if ((Window->ActiveTextEdit != NIL)
  1263.             && TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1264.             {
  1265.                 EnableMenuItem(mEnterSelection);
  1266.             }
  1267.         SetItemCheckmark(Window->MyMenuItem);
  1268.     }
  1269.  
  1270.  
  1271. void                                WaveTableWindowDoMenuCommand(WaveTableWindowRec* Window,
  1272.                                             MenuItemType* MenuItem)
  1273.     {
  1274.         CheckPtrExistence(Window);
  1275.         if (MainWindowDoGlobalMenuItem(Window->MainWindow,MenuItem))
  1276.             {
  1277.             }
  1278.         else if (MenuItem == mPaste)
  1279.             {
  1280.                 if (Window->ActiveTextEdit != NIL)
  1281.                     {
  1282.                         TextEditDoMenuPaste(Window->ActiveTextEdit);
  1283.                     }
  1284.             }
  1285.         else if (MenuItem == mCut)
  1286.             {
  1287.                 if (Window->ActiveTextEdit != NIL)
  1288.                     {
  1289.                         TextEditDoMenuCut(Window->ActiveTextEdit);
  1290.                     }
  1291.             }
  1292.         else if (MenuItem == mCopy)
  1293.             {
  1294.                 if (Window->ActiveTextEdit != NIL)
  1295.                     {
  1296.                         TextEditDoMenuCopy(Window->ActiveTextEdit);
  1297.                     }
  1298.             }
  1299.         else if (MenuItem == mClear)
  1300.             {
  1301.                 if (Window->ActiveTextEdit != NIL)
  1302.                     {
  1303.                         TextEditDoMenuClear(Window->ActiveTextEdit);
  1304.                     }
  1305.             }
  1306.         else if (MenuItem == mSelectAll)
  1307.             {
  1308.                 if (Window->ActiveTextEdit != NIL)
  1309.                     {
  1310.                         TextEditDoMenuSelectAll(Window->ActiveTextEdit);
  1311.                     }
  1312.             }
  1313.         else if (MenuItem == mUndo)
  1314.             {
  1315.                 if (Window->ActiveTextEdit != NIL)
  1316.                     {
  1317.                         TextEditDoMenuUndo(Window->ActiveTextEdit);
  1318.                     }
  1319.                  else
  1320.                     {
  1321.                         WaveTableStorDispRec*        Temp;
  1322.  
  1323.                         Temp = Window->UndoBackupWaveTable;
  1324.                         Window->UndoBackupWaveTable = Window->WaveTableData;
  1325.                         Window->WaveTableData = Temp;
  1326.                         Window->WaveDataModified = True;
  1327.                         WaveTableWindowUpdateAllParameters(Window);
  1328.                     }
  1329.             }
  1330.         else if (MenuItem == mCloseFile)
  1331.             {
  1332.                 WaveTableWindowClose(Window);
  1333.             }
  1334.         else if (MenuItem == mEvaluateCalc)
  1335.             {
  1336.                 WaveTableWindowEvaluateFunction(Window);
  1337.             }
  1338.         else if (MenuItem == mShiftLeft)
  1339.             {
  1340.                 TextEditShiftSelectionLeftOneTab(Window->ActiveTextEdit);
  1341.             }
  1342.         else if (MenuItem == mShiftRight)
  1343.             {
  1344.                 TextEditShiftSelectionRightOneTab(Window->ActiveTextEdit);
  1345.             }
  1346.         else if (MenuItem == mBalanceParens)
  1347.             {
  1348.                 TextEditBalanceParens(Window->ActiveTextEdit);
  1349.             }
  1350.         else if (MenuItem == mDeleteObject)
  1351.             {
  1352.                 WaveTableListDeleteWaveTable(Window->WaveTableList,Window->WaveTableObject);
  1353.             }
  1354.         else if (MenuItem == mFind)
  1355.             {
  1356.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1357.                     {
  1358.                         if (Window->ActiveTextEdit != NIL)
  1359.                             {
  1360.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1361.                             }
  1362.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1363.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1364.                     }
  1365.                 switch (DoFindDialog(&GlobalSearchString,&GlobalReplaceString,
  1366.                     mCut,mPaste,mCopy,mUndo,mSelectAll,mClear))
  1367.                     {
  1368.                         default:
  1369.                             EXECUTE(PRERR(ForceAbort,
  1370.                                 "WaveTableWindowDoMenuCommand:  bad value from DoFindDialog"));
  1371.                             break;
  1372.                         case eFindCancel:
  1373.                         case eDontFind:
  1374.                             break;
  1375.                         case eFindFromStart:
  1376.                             SetTextEditInsertionPoint(Window->ActiveTextEdit,0,0);
  1377.                             TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1378.                             TextEditShowSelection(Window->ActiveTextEdit);
  1379.                             break;
  1380.                         case eFindAgain:
  1381.                             TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1382.                             TextEditShowSelection(Window->ActiveTextEdit);
  1383.                             break;
  1384.                     }
  1385.             }
  1386.         else if (MenuItem == mFindAgain)
  1387.             {
  1388.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1389.                     {
  1390.                         if (Window->ActiveTextEdit != NIL)
  1391.                             {
  1392.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1393.                             }
  1394.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1395.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1396.                     }
  1397.                 TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1398.                 TextEditShowSelection(Window->ActiveTextEdit);
  1399.             }
  1400.         else if (MenuItem == mReplace)
  1401.             {
  1402.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1403.                     {
  1404.                         if (Window->ActiveTextEdit != NIL)
  1405.                             {
  1406.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1407.                             }
  1408.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1409.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1410.                     }
  1411.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1412.                     {
  1413.                         TextEditInsertRawData(Window->ActiveTextEdit,GlobalReplaceString,
  1414.                             SYSTEMLINEFEED);
  1415.                     }
  1416.             }
  1417.         else if (MenuItem == mReplaceAndFindAgain)
  1418.             {
  1419.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1420.                     {
  1421.                         if (Window->ActiveTextEdit != NIL)
  1422.                             {
  1423.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1424.                             }
  1425.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1426.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1427.                     }
  1428.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1429.                     {
  1430.                         TextEditInsertRawData(Window->ActiveTextEdit,GlobalReplaceString,
  1431.                             SYSTEMLINEFEED);
  1432.                         TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1433.                         TextEditShowSelection(Window->ActiveTextEdit);
  1434.                     }
  1435.             }
  1436.         else if (MenuItem == mEnterSelection)
  1437.             {
  1438.                 if (Window->ActiveTextEdit != NIL)
  1439.                     {
  1440.                         char*                        NewString;
  1441.  
  1442.                         NewString = TextEditGetSelection(Window->ActiveTextEdit);
  1443.                         if (NewString != NIL)
  1444.                             {
  1445.                                 ReleasePtr(GlobalSearchString);
  1446.                                 GlobalSearchString = NewString;
  1447.                             }
  1448.                     }
  1449.             }
  1450.         else
  1451.             {
  1452.                 EXECUTE(PRERR(AllowResume,"WaveTableWindowDoMenuCommand:  unknown menu command"));
  1453.             }
  1454.     }
  1455.  
  1456.  
  1457. /* get a copy of the wave table's name */
  1458. char*                                WaveTableWindowGetNameCopy(WaveTableWindowRec* Window)
  1459.     {
  1460.         char*                            TextCopy;
  1461.  
  1462.         CheckPtrExistence(Window);
  1463.         TextCopy = TextEditGetRawData(Window->NameEdit,"\x0a");
  1464.         if (TextCopy != NIL)
  1465.             {
  1466.                 SetTag(TextCopy,"WaveTableWindowNameCopy");
  1467.             }
  1468.         return TextCopy;
  1469.     }
  1470.  
  1471.  
  1472. /* get a copy of the wave table's formula */
  1473. char*                                WaveTableWindowGetFormulaCopy(WaveTableWindowRec* Window)
  1474.     {
  1475.         char*                            TextCopy;
  1476.  
  1477.         CheckPtrExistence(Window);
  1478.         TextCopy = TextEditGetRawData(Window->FunctionEdit,"\x0a");
  1479.         if (TextCopy != NIL)
  1480.             {
  1481.                 SetTag(TextCopy,"WaveTableWindowFormulaCopy");
  1482.             }
  1483.         return TextCopy;
  1484.     }
  1485.  
  1486.  
  1487. /* get the number of bits used for the wave table */
  1488. NumBitsType                    WaveTableWindowGetNumBits(WaveTableWindowRec* Window)
  1489.     {
  1490.         CheckPtrExistence(Window);
  1491.         if (GetIconButtonState(Window->Bits16Button))
  1492.             {
  1493.                 return eSample16bit;
  1494.             }
  1495.          else
  1496.             {
  1497.                 return eSample8bit;
  1498.             }
  1499.     }
  1500.  
  1501.  
  1502. /* get the number of periods in the wave table */
  1503. long                                WaveTableWindowGetNumTables(WaveTableWindowRec* Window)
  1504.     {
  1505.         CheckPtrExistence(Window);
  1506.         return WaveTableStorDispNumTables(Window->WaveTableData);
  1507.     }
  1508.  
  1509.  
  1510. /* get the number of frames in each period of the wave table */
  1511. long                                WaveTableWindowGetNumFramesPerTable(WaveTableWindowRec* Window)
  1512.     {
  1513.         CheckPtrExistence(Window);
  1514.         return WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  1515.     }
  1516.  
  1517.  
  1518. /* get the pitch at which the wave table should be tested */
  1519. double                            WaveTableWindowGetPitch(WaveTableWindowRec* Window)
  1520.     {
  1521.         char*                            Text;
  1522.         double                        ReturnValue;
  1523.  
  1524.         CheckPtrExistence(Window);
  1525.         Text = TextEditGetRawData(Window->TestFrequency,SYSTEMLINEFEED);
  1526.         if (Text != NIL)
  1527.             {
  1528.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1529.                 ReleasePtr(Text);
  1530.             }
  1531.          else
  1532.             {
  1533.                 ReturnValue = 261.625565300598635;
  1534.             }
  1535.         return ReturnValue;
  1536.     }
  1537.  
  1538.  
  1539. /* get the duration (seconds) for the increasing table index phase of the test */
  1540. double                            WaveTableWindowGetAscendingDuration(WaveTableWindowRec* Window)
  1541.     {
  1542.         char*                            Text;
  1543.         double                        ReturnValue;
  1544.  
  1545.         CheckPtrExistence(Window);
  1546.         Text = TextEditGetRawData(Window->TestAttackDuration,SYSTEMLINEFEED);
  1547.         if (Text != NIL)
  1548.             {
  1549.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1550.                 ReleasePtr(Text);
  1551.             }
  1552.          else
  1553.             {
  1554.                 ReturnValue = 1;
  1555.             }
  1556.         return ReturnValue;
  1557.     }
  1558.  
  1559.  
  1560. /* get the duration (seconds) for the decreasing table index phase of the test */
  1561. double                            WaveTableWindowGetDescendingDuration(WaveTableWindowRec* Window)
  1562.     {
  1563.         char*                            Text;
  1564.         double                        ReturnValue;
  1565.  
  1566.         CheckPtrExistence(Window);
  1567.         Text = TextEditGetRawData(Window->TestDecayDuration,SYSTEMLINEFEED);
  1568.         if (Text != NIL)
  1569.             {
  1570.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1571.                 ReleasePtr(Text);
  1572.             }
  1573.          else
  1574.             {
  1575.                 ReturnValue = 2;
  1576.             }
  1577.         return ReturnValue;
  1578.     }
  1579.  
  1580.  
  1581. /* get the sampling rate to use for the test */
  1582. long                                WaveTableWindowGetTestSamplingRate(WaveTableWindowRec* Window)
  1583.     {
  1584.         char*                            Text;
  1585.         double                        ReturnValue;
  1586.  
  1587.         CheckPtrExistence(Window);
  1588.         Text = TextEditGetRawData(Window->TestSamplingRate,SYSTEMLINEFEED);
  1589.         if (Text != NIL)
  1590.             {
  1591.                 ReturnValue = StringToInteger(Text,PtrSize(Text));
  1592.                 ReleasePtr(Text);
  1593.             }
  1594.          else
  1595.             {
  1596.                 ReturnValue = 22050;
  1597.             }
  1598.         return ReturnValue;
  1599.     }
  1600.  
  1601.  
  1602. /* reset the scroll bar indices and redraw it */
  1603. void                                WaveTableWindowUpdateScrollBar(WaveTableWindowRec* Window)
  1604.     {
  1605.         CheckPtrExistence(Window);
  1606.         SetMaxScrollIndex(Window->TableScroll,WaveTableWindowGetNumTables(Window));
  1607.         SetScrollIndex(Window->TableScroll,Window->CurrentlyVisibleTable);
  1608.     }
  1609.  
  1610.  
  1611. /* redraw the wave table waveform box */
  1612. void                                WaveTableWindowRedrawTable(WaveTableWindowRec* Window)
  1613.     {
  1614.         OrdType                        WindowWidth;
  1615.         OrdType                        WindowHeight;
  1616.         long                            Scan;
  1617.         long                            Limit;
  1618.         OrdType                        PreviousYValue;
  1619.         OrdType                        PreviousXValue;
  1620.         MyBoolean                    PreviousYValueIsValid;
  1621.  
  1622.         CheckPtrExistence(Window);
  1623.         WindowWidth = GetWindowWidth(Window->ScreenID);
  1624.         WindowHeight = GetWindowHeight(Window->ScreenID);
  1625.         SetClipRect(Window->ScreenID,WAVEFORMVIEWX,WAVEFORMVIEWY,
  1626.             WAVEFORMVIEWWIDTH(WindowWidth),WAVEFORMVIEWHEIGHT(WindowHeight));
  1627.         DrawBoxFrame(Window->ScreenID,eBlack,WAVEFORMVIEWX,WAVEFORMVIEWY,
  1628.             WAVEFORMVIEWWIDTH(WindowWidth),WAVEFORMVIEWHEIGHT(WindowHeight));
  1629.         if (WaveTableWindowGetNumTables(Window) == 0)
  1630.             {
  1631.                 DrawBoxPaint(Window->ScreenID,eLightGrey,WAVEFORMVIEWX + 1,WAVEFORMVIEWY + 1,
  1632.                     WAVEFORMVIEWWIDTH(WindowWidth) - 2,WAVEFORMVIEWHEIGHT(WindowHeight) - 2);
  1633.                 return;
  1634.             }
  1635.         DrawBoxErase(Window->ScreenID,WAVEFORMVIEWX + 1,WAVEFORMVIEWY + 1,
  1636.             WAVEFORMVIEWWIDTH(WindowWidth) - 2,WAVEFORMVIEWHEIGHT(WindowHeight) - 2);
  1637.         ERROR((Window->CurrentlyVisibleTable < 0) || (Window->CurrentlyVisibleTable
  1638.             >= WaveTableWindowGetNumTables(Window)),PRERR(ForceAbort,
  1639.             "WaveTableWindowRedrawTable:  current table index is out of range"));
  1640.         Limit = WaveTableWindowGetNumFramesPerTable(Window);
  1641.         PreviousYValueIsValid = False;
  1642.         for (Scan = 0; Scan < Limit; Scan += 1)
  1643.             {
  1644.                 double                    Value;
  1645.                 OrdType                    ThisYValue;
  1646.                 OrdType                    ThisXValue;
  1647.  
  1648.                 Value = largefixed2double(WaveTableStorDispGetFrame(Window->WaveTableData,
  1649.                     Window->CurrentlyVisibleTable,Scan));
  1650.                 ThisYValue = (1 - ((Value + 1) / 2)) * (WAVEFORMVIEWHEIGHT(WindowHeight) - 3)
  1651.                     + WAVEFORMVIEWY + 1;
  1652.                 ThisXValue = (Scan * (WAVEFORMVIEWWIDTH(WindowWidth) - 2))
  1653.                     / (Limit - 1) + WAVEFORMVIEWX + 1;
  1654.                 if (!PreviousYValueIsValid)
  1655.                     {
  1656.                         PreviousYValueIsValid = True;
  1657.                         PreviousYValue = ThisYValue;
  1658.                         PreviousXValue = ThisXValue;
  1659.                     }
  1660.                 DrawLine(Window->ScreenID,eBlack,PreviousXValue,PreviousYValue,
  1661.                     ThisXValue - PreviousXValue,ThisYValue - PreviousYValue);
  1662.                 PreviousYValue = ThisYValue;
  1663.                 PreviousXValue = ThisXValue;
  1664.             }
  1665.     }
  1666.  
  1667.  
  1668. /* the name of the file has changed, so change the title bar.  the string is a */
  1669. /* non-null-terminated, and the caller is responsible for disposing of it */
  1670. void                                WaveTableWindowGlobalNameChange(WaveTableWindowRec* Window,
  1671.                                             char* NewFilename)
  1672.     {
  1673.         char*                            LocalNameCopy;
  1674.  
  1675.         CheckPtrExistence(Window);
  1676.         CheckPtrExistence(NewFilename);
  1677.         LocalNameCopy = WaveTableWindowGetNameCopy(Window);
  1678.         if (LocalNameCopy != NIL)
  1679.             {
  1680.                 char*                            SeparatorString;
  1681.  
  1682.                 SeparatorString = StringToBlockCopy(":  ");
  1683.                 if (SeparatorString != NIL)
  1684.                     {
  1685.                         char*                            LeftHalfOfString;
  1686.  
  1687.                         LeftHalfOfString = ConcatBlockCopy(NewFilename,SeparatorString);
  1688.                         if (LeftHalfOfString != NIL)
  1689.                             {
  1690.                                 char*                            TotalString;
  1691.  
  1692.                                 TotalString = ConcatBlockCopy(LeftHalfOfString,LocalNameCopy);
  1693.                                 if (TotalString != NIL)
  1694.                                     {
  1695.                                         char*                            NullTerminatedString;
  1696.  
  1697.                                         NullTerminatedString = BlockToStringCopy(TotalString);
  1698.                                         if (NullTerminatedString != NIL)
  1699.                                             {
  1700.                                                 SetWindowName(Window->ScreenID,NullTerminatedString);
  1701.                                                 ChangeItemName(Window->MyMenuItem,NullTerminatedString);
  1702.                                                 ReleasePtr(NullTerminatedString);
  1703.                                             }
  1704.                                         ReleasePtr(TotalString);
  1705.                                     }
  1706.                                 ReleasePtr(LeftHalfOfString);
  1707.                             }
  1708.                         ReleasePtr(SeparatorString);
  1709.                     }
  1710.                 ReleasePtr(LocalNameCopy);
  1711.             }
  1712.     }
  1713.  
  1714.  
  1715. /* reset the title bar name even if the document name hasn't changed */
  1716. void                                WaveTableWindowResetTitlebar(WaveTableWindowRec* Window)
  1717.     {
  1718.         char*                            DocumentName;
  1719.  
  1720.         CheckPtrExistence(Window);
  1721.         DocumentName = GetCopyOfDocumentName(Window->MainWindow);
  1722.         if (DocumentName != NIL)
  1723.             {
  1724.                 WaveTableWindowGlobalNameChange(Window,DocumentName);
  1725.                 ReleasePtr(DocumentName);
  1726.             }
  1727.     }
  1728.  
  1729.  
  1730. /* set the number of periods to that stored in the edit box, and interpolate */
  1731. /* the periods. */
  1732. void                                WaveTableWindowSetNewNumTables(WaveTableWindowRec* Window)
  1733.     {
  1734.         long                            OriginalNumTables;
  1735.         long                            NewNumTables;
  1736.  
  1737.         CheckPtrExistence(Window);
  1738.         OriginalNumTables = WaveTableWindowGetNumTables(Window);
  1739.         NewNumTables = DoNumberDialog("Enter new number of tables:",OriginalNumTables,
  1740.             mCut,mPaste,mCopy,mUndo,mSelectAll,mClear);
  1741.         if (NewNumTables != OriginalNumTables)
  1742.             {
  1743.                 WaveTableStorDispRec*    NewTable;
  1744.                 long                                    TableScan;
  1745.  
  1746.                 /* free up undo-backup info */
  1747.                 if (Window->UndoBackupWaveTable != NIL)
  1748.                     {
  1749.                         DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  1750.                         Window->UndoBackupWaveTable = NIL;
  1751.                     }
  1752.  
  1753.                 /* build new table */
  1754.                 NewTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(Window->WaveTableData),
  1755.                     WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  1756.                 if (NewTable == NIL)
  1757.                     {
  1758.                      MemoryFailurePoint1:
  1759.                         AlertHalt("There is not enough memory available to resize the wave table.",NIL);
  1760.                         return;
  1761.                     }
  1762.                 for (TableScan = 0; TableScan < NewNumTables; TableScan += 1)
  1763.                     {
  1764.                         if (!WaveTableStorDispAppendEntry(NewTable))
  1765.                             {
  1766.                              MemoryFailurePoint2:
  1767.                                 DisposeWaveTableStorDisp(NewTable);
  1768.                                 goto MemoryFailurePoint1;
  1769.                             }
  1770.                     }
  1771.  
  1772.                 if ((NewNumTables != 0) && (OriginalNumTables != 0))
  1773.                     {
  1774.                         long                        NumFrames;
  1775.  
  1776.                         NumFrames = WaveTableStorDispNumFramesPerTable(NewTable);
  1777.                         /* store the neat things into the table.  we use linear interpolation */
  1778.                         /* between adjacent tables to create new tables. */
  1779.                         for (TableScan = 0; TableScan < NewNumTables; TableScan += 1)
  1780.                             {
  1781.                                 double                        LeftWeight;
  1782.                                 double                        RightWeight;
  1783.                                 long                            LeftIndex;
  1784.                                 long                            RightIndex;
  1785.                                 double                        PrecisePositioning;
  1786.                                 long                            FrameScan;
  1787.  
  1788.                                 if (NewNumTables > 1)
  1789.                                     {
  1790.                                         PrecisePositioning = (double)TableScan / (double)(NewNumTables - 1)
  1791.                                             * (double)(OriginalNumTables - 1);
  1792.                                     }
  1793.                                  else
  1794.                                     {
  1795.                                         PrecisePositioning = (double)(OriginalNumTables - 1) / 2;
  1796.                                     }
  1797.                                 LeftIndex = (long)PrecisePositioning;
  1798.                                 RightIndex = LeftIndex + 1;
  1799.                                 RightWeight = PrecisePositioning - LeftIndex;
  1800.                                 LeftWeight = 1 - RightWeight;
  1801.                                 for (FrameScan = 0; FrameScan < NumFrames; FrameScan += 1)
  1802.                                     {
  1803.                                         double                        LeftValue;
  1804.                                         double                        RightValue;
  1805.                                         double                        ResultantComposite;
  1806.  
  1807.                                         LeftValue = largefixed2double(WaveTableStorDispGetFrame(
  1808.                                             Window->WaveTableData,LeftIndex,FrameScan));
  1809.                                         if (RightIndex < OriginalNumTables)
  1810.                                             {
  1811.                                                 RightValue = largefixed2double(WaveTableStorDispGetFrame(
  1812.                                                     Window->WaveTableData,RightIndex,FrameScan));
  1813.                                             }
  1814.                                          else
  1815.                                             {
  1816.                                                 RightValue = 0;
  1817.                                                 ERROR(RightWeight != 0,PRERR(ForceAbort,
  1818.                                                     "WaveTableWindowSetNewNumTables:  on last table, but right "
  1819.                                                     "weight is non-zero."));
  1820.                                             }
  1821.                                         ResultantComposite = LeftValue * LeftWeight
  1822.                                             + RightValue * RightWeight;
  1823.                                         WaveTableStorDispSetFrame(NewTable,TableScan,FrameScan,
  1824.                                             double2largefixed(ResultantComposite));
  1825.                                     }
  1826.                             }
  1827.                     }
  1828.  
  1829.                 /* save it */
  1830.                 Window->UndoBackupWaveTable = Window->WaveTableData;
  1831.                 Window->WaveTableData = NewTable;
  1832.                 WaveTableWindowUpdateAllParameters(Window);
  1833.                 Window->WaveDataModified = True;
  1834.             }
  1835.     }
  1836.  
  1837.  
  1838. /* set the number of periods edit box to be the same as the data */
  1839. void                                WaveTableWindowUpdateTableCountEdit(WaveTableWindowRec* Window)
  1840.     {
  1841.         char*                            StringTemp;
  1842.  
  1843.         CheckPtrExistence(Window);
  1844.         StringTemp = IntegerToString(WaveTableObjectGetNumTables(Window->WaveTableObject));
  1845.         if (StringTemp == NIL)
  1846.             {
  1847.                 return;
  1848.             }
  1849.         TextEditNewRawData(Window->NumTablesEdit,StringTemp,"\x0a");
  1850.         ReleasePtr(StringTemp);
  1851.         TextEditHasBeenSaved(Window->NumTablesEdit);
  1852.     }
  1853.  
  1854.  
  1855. /* set the number of frames edit box to be the same as the data */
  1856. void                                WaveTableWindowUpdateFrameCountEdit(WaveTableWindowRec* Window)
  1857.     {
  1858.         char*                            StringTemp;
  1859.  
  1860.         CheckPtrExistence(Window);
  1861.         StringTemp = IntegerToString(
  1862.             WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  1863.         if (StringTemp == NIL)
  1864.             {
  1865.                 return;
  1866.             }
  1867.         TextEditNewRawData(Window->NumFramesEdit,StringTemp,"\x0a");
  1868.         ReleasePtr(StringTemp);
  1869.         TextEditHasBeenSaved(Window->NumFramesEdit);
  1870.     }
  1871.  
  1872.  
  1873. /* set all edit boxes to be the same as the underlying data */
  1874. void                                WaveTableWindowUpdateAllParameters(WaveTableWindowRec* Window)
  1875.     {
  1876.         if (Window->CurrentlyVisibleTable
  1877.             > WaveTableObjectGetNumTables(Window->WaveTableObject) - 1)
  1878.             {
  1879.                 Window->CurrentlyVisibleTable
  1880.                     = WaveTableObjectGetNumTables(Window->WaveTableObject) - 1;
  1881.             }
  1882.         if (Window->CurrentlyVisibleTable < 0)
  1883.             {
  1884.                 Window->CurrentlyVisibleTable = 0;
  1885.             }
  1886.         WaveTableWindowUpdateTableCountEdit(Window);
  1887.         WaveTableWindowUpdateFrameCountEdit(Window);
  1888.         WaveTableWindowUpdateScrollBar(Window);
  1889.         WaveTableWindowRedrawTable(Window);
  1890.     }
  1891.  
  1892.  
  1893. /* give a dialog box asking for a new number of frames, and then interpolate all */
  1894. /* of the wave periods. */
  1895. void                                WaveTableWindowSetNewNumFrames(WaveTableWindowRec* Window)
  1896.     {
  1897.         long                            OriginalNumFrames;
  1898.         long                            NewNumFrames;
  1899.         WaveTableStorDispRec*    NewTable;
  1900.         long                            NumberOfTables;
  1901.         long                            TableScan;
  1902.  
  1903.         CheckPtrExistence(Window);
  1904.         OriginalNumFrames = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  1905.         NewNumFrames = AskForNewWaveTableSize(OriginalNumFrames);
  1906.  
  1907.         if (NewNumFrames == OriginalNumFrames)
  1908.             {
  1909.                 return;
  1910.             }
  1911.  
  1912.         /* dump the undo backup information */
  1913.         if (Window->UndoBackupWaveTable != NIL)
  1914.             {
  1915.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  1916.                 Window->UndoBackupWaveTable = NIL;
  1917.             }
  1918.  
  1919.         /* create a new table */
  1920.         NewTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(Window->WaveTableData),
  1921.             NewNumFrames);
  1922.         if (NewTable == NIL)
  1923.             {
  1924.              MemoryFailurePoint1:
  1925.                 AlertHalt("There is not enough memory available to resample the wave table.",NIL);
  1926.                 return;
  1927.             }
  1928.         NumberOfTables = WaveTableStorDispNumTables(Window->WaveTableData);
  1929.         for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1930.             {
  1931.                 if (!WaveTableStorDispAppendEntry(NewTable))
  1932.                     {
  1933.                      MemoryFailurePoint2:
  1934.                         DisposeWaveTableStorDisp(NewTable);
  1935.                         goto MemoryFailurePoint1;
  1936.                     }
  1937.             }
  1938.  
  1939.         /* this one handles interpolating between entries to expand the table */
  1940.         if (NewNumFrames > OriginalNumFrames)
  1941.             {
  1942.                 long                            ExpansionFactor;
  1943.  
  1944.                 ExpansionFactor = NewNumFrames / OriginalNumFrames;
  1945.                 for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1946.                     {
  1947.                         long                            NewFrameScan;
  1948.  
  1949.                         for (NewFrameScan = 0; NewFrameScan < NewNumFrames; NewFrameScan += 1)
  1950.                             {
  1951.                                 double                        LeftWeight;
  1952.                                 double                        RightWeight;
  1953.                                 long                            LeftIndex;
  1954.                                 long                            RightIndex;
  1955.                                 double                        PrecisePositioning;
  1956.                                 long                            FrameScan;
  1957.                                 double                        LeftValue;
  1958.                                 double                        RightValue;
  1959.                                 double                        ResultantComposite;
  1960.  
  1961.                                 PrecisePositioning = (double)NewFrameScan / (double)NewNumFrames
  1962.                                     * (double)OriginalNumFrames;
  1963.                                 LeftIndex = (long)PrecisePositioning;
  1964.                                 RightIndex = LeftIndex + 1;
  1965.                                 RightWeight = PrecisePositioning - LeftIndex;
  1966.                                 LeftWeight = 1 - RightWeight;
  1967.                                 LeftValue = largefixed2double(WaveTableStorDispGetFrame(
  1968.                                     Window->WaveTableData,TableScan,LeftIndex));
  1969.                                 RightValue = largefixed2double(WaveTableStorDispGetFrame(
  1970.                                     Window->WaveTableData,TableScan,RightIndex % OriginalNumFrames));
  1971.                                 ResultantComposite = LeftValue * LeftWeight
  1972.                                     + RightValue * RightWeight;
  1973.                                 WaveTableStorDispSetFrame(NewTable,TableScan,NewFrameScan,
  1974.                                     double2largefixed(ResultantComposite));
  1975.                             }
  1976.                     }
  1977.             }
  1978.  
  1979.         /* this one handles averaging the frames for table compression */
  1980.         else
  1981.             {
  1982.                 long                            FoldingFactor;
  1983.  
  1984.                 FoldingFactor = OriginalNumFrames / NewNumFrames;
  1985.                 for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1986.                     {
  1987.                         long                            NewFrameScan;
  1988.  
  1989.                         for (NewFrameScan = 0; NewFrameScan < NewNumFrames; NewFrameScan += 1)
  1990.                             {
  1991.                                 double                        Accumulator;
  1992.                                 long                            SumScan;
  1993.                                 double                        Average;
  1994.  
  1995.                                 Accumulator = 0;
  1996.                                 for (SumScan = 0; SumScan < FoldingFactor; SumScan += 1)
  1997.                                     {
  1998.                                         Accumulator += largefixed2double(WaveTableStorDispGetFrame(
  1999.                                             Window->WaveTableData,TableScan,
  2000.                                             NewFrameScan * FoldingFactor + SumScan));
  2001.                                     }
  2002.                                 Average = Accumulator / FoldingFactor;
  2003.                                 WaveTableStorDispSetFrame(NewTable,TableScan,NewFrameScan,
  2004.                                     double2largefixed(Average));
  2005.                             }
  2006.                     }
  2007.             }
  2008.  
  2009.         Window->UndoBackupWaveTable = Window->WaveTableData;
  2010.         Window->WaveTableData = NewTable;
  2011.         WaveTableWindowUpdateAllParameters(Window);
  2012.         Window->WaveDataModified = True;
  2013.     }
  2014.  
  2015.  
  2016. /* argument list for wave table function thang */
  2017. static FunctionParamRec        ArgumentList[] =
  2018.     {
  2019.         {"frames",eInteger},
  2020.         {"tables",eInteger},
  2021.         {"data",eArrayOfFixed}
  2022.     };
  2023. #define ARGLISTLENGTH (sizeof(ArgumentList) / sizeof(ArgumentList[0]))
  2024.  
  2025.  
  2026. /* evaluate the wave formula and update the wave data */
  2027. void                                WaveTableWindowEvaluateFunction(WaveTableWindowRec* Window)
  2028.     {
  2029.         char*                                Blob;
  2030.         PcodeRec*                        FuncCode;
  2031.         CompileErrors                Error;
  2032.         long                                LineNumber;
  2033.         ParamStackRec*            ParamList;
  2034.         EvalErrors                    OtherError;
  2035.         OpcodeRec*                    ErrorOpcode;
  2036.         long                                OffendingInstruction;
  2037.         DataTypes                        ReturnType;
  2038.         long                                TotalFramesPerTable;
  2039.         long                                TotalNumTables;
  2040.  
  2041.         CheckPtrExistence(Window);
  2042.  
  2043.         /* bring the world up to date */
  2044.         if (!MainWindowMakeUpToDateFunctions(Window->MainWindow))
  2045.             {
  2046.                 return;
  2047.             }
  2048.  
  2049.         /* prepare the text blob to be evaluated */
  2050.         Blob = TextEditGetRawData(Window->FunctionEdit,"\x0a");
  2051.         if (Blob == NIL)
  2052.             {
  2053.              FailurePoint1:
  2054.                 AlertHalt("There is not enough memory available to compile the expression.",NIL);
  2055.                 return;
  2056.             }
  2057.  
  2058.         if (Window->UndoBackupWaveTable != NIL)
  2059.             {
  2060.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  2061.                 Window->UndoBackupWaveTable = NIL;
  2062.             }
  2063.  
  2064.         /* perform compilation */
  2065.         Error = CompileSpecialFunction(ArgumentList,ARGLISTLENGTH,&LineNumber,
  2066.             &ReturnType,Blob,&FuncCode);
  2067.         ReleasePtr(Blob);
  2068.         if (Error != eCompileNoError)
  2069.             {
  2070.                 SetTextEditSelection(Window->FunctionEdit,LineNumber - 1,0,LineNumber,0);
  2071.                 TextEditShowSelection(Window->FunctionEdit);
  2072.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  2073.                 return;
  2074.             }
  2075.  
  2076.         /* try to evaluate the code */
  2077.         ParamList = NewParamStack();
  2078.         if (ParamList == NIL)
  2079.             {
  2080.              SecondFailurePoint1:
  2081.                 DisposePcode(FuncCode);
  2082.                 AlertHalt("There is not enough memory available to evaluate the expression.",NIL);
  2083.                 return;
  2084.             }
  2085.         TotalFramesPerTable = WaveTableWindowGetNumFramesPerTable(Window);
  2086.         TotalNumTables = WaveTableWindowGetNumTables(Window);
  2087.         /* add a space for the return value */
  2088.         if (!AddIntegerToStack(ParamList,0))
  2089.             {
  2090.              SecondFailurePoint2:
  2091.                 DisposeParamStack(ParamList);
  2092.                 goto SecondFailurePoint1;
  2093.             }
  2094.         /* frames */
  2095.         if (!AddIntegerToStack(ParamList,TotalFramesPerTable))
  2096.             {
  2097.                 goto SecondFailurePoint2;
  2098.             }
  2099.         /* tables */
  2100.         if (!AddIntegerToStack(ParamList,TotalNumTables))
  2101.             {
  2102.                 goto SecondFailurePoint2;
  2103.             }
  2104.         /* data */
  2105.         {
  2106.             largefixedsigned*        TheDataBlock;
  2107.             long                                TableScan;
  2108.             long                                FrameScan;
  2109.  
  2110.             TheDataBlock = (largefixedsigned*)AllocPtrCanFail(sizeof(largefixedsigned)
  2111.                 * TotalFramesPerTable * TotalNumTables,"WaveTableWindowEvaluateFunction: array");
  2112.             if (TheDataBlock == NIL)
  2113.                 {
  2114.                     goto SecondFailurePoint2;
  2115.                 }
  2116.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2117.                 {
  2118.                     for (FrameScan = 0; FrameScan < TotalFramesPerTable; FrameScan += 1)
  2119.                         {
  2120.                             PRNGCHK(TheDataBlock,&(TheDataBlock[TableScan * TotalFramesPerTable
  2121.                                 + FrameScan]),sizeof(TheDataBlock[TableScan * TotalFramesPerTable
  2122.                                 + FrameScan]));
  2123.                             TheDataBlock[TableScan * TotalFramesPerTable + FrameScan]
  2124.                                 = WaveTableStorDispGetFrame(Window->WaveTableData,TableScan,FrameScan);
  2125.                         }
  2126.                 }
  2127.             if (!AddArrayToStack(ParamList,TheDataBlock))
  2128.                 {
  2129.                     ReleasePtr((char*)TheDataBlock);
  2130.                     goto SecondFailurePoint2;
  2131.                 }
  2132.         }
  2133.  
  2134.         /* executing the actual code */
  2135.         OtherError = EvaluatePcode(ParamList,FuncCode,
  2136.             Window->CodeCenter,&ErrorOpcode,&OffendingInstruction,Window->MainWindow,
  2137.             &MainWindowGetSampleLeftCopy,&MainWindowGetSampleRightCopy,
  2138.             &MainWindowGetSampleMonoCopy,&MainWindowGetWaveTableFrameCount,
  2139.             &MainWindowGetWaveTableTableCount,&MainWindowGetWaveTableArray);
  2140.         if (OtherError != eEvalNoError)
  2141.             {
  2142.                 char*                    FuncNameString;
  2143.                 FuncCodeRec*    ErrorFunction;
  2144.                 MyBoolean            SuccessFlag;
  2145.  
  2146.                 /* present error message */
  2147.                 SuccessFlag = False;
  2148.                 ErrorFunction = GetFunctionFromOpcode(Window->CodeCenter,ErrorOpcode);
  2149.                 if (ErrorFunction == NIL)
  2150.                     {
  2151.                         FuncNameString = StringToBlockCopy("<anonymous>");
  2152.                     }
  2153.                  else
  2154.                     {
  2155.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  2156.                     }
  2157.                 if (FuncNameString != NIL)
  2158.                     {
  2159.                         char*                    Key;
  2160.  
  2161.                         Key = StringToBlockCopy("_");
  2162.                         if (Key != NIL)
  2163.                             {
  2164.                                 char*                    BaseMessage;
  2165.  
  2166.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  2167.                                 if (BaseMessage != NIL)
  2168.                                     {
  2169.                                         char*                    FixedMessage1;
  2170.  
  2171.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  2172.                                         if (FixedMessage1 != NIL)
  2173.                                             {
  2174.                                                 char*                    NumberStr;
  2175.  
  2176.                                                 NumberStr = IntegerToString(OffendingInstruction);
  2177.                                                 if (NumberStr != NIL)
  2178.                                                     {
  2179.                                                         char*                    FixedMessage2;
  2180.  
  2181.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  2182.                                                         if (FixedMessage2 != NIL)
  2183.                                                             {
  2184.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  2185.                                                                 SuccessFlag = True;
  2186.                                                                 ReleasePtr(FixedMessage2);
  2187.                                                             }
  2188.                                                         ReleasePtr(NumberStr);
  2189.                                                     }
  2190.                                                 ReleasePtr(FixedMessage1);
  2191.                                             }
  2192.                                         ReleasePtr(BaseMessage);
  2193.                                     }
  2194.                                 ReleasePtr(Key);
  2195.                             }
  2196.                         ReleasePtr(FuncNameString);
  2197.                     }
  2198.                 if (!SuccessFlag)
  2199.                     {
  2200.                         AlertHalt("There is not enough memory available to show "
  2201.                             "the compile error message.",NIL);
  2202.                     }
  2203.                 DisposeParamStack(ParamList);
  2204.                 DisposePcode(FuncCode);
  2205.                 return;
  2206.             }
  2207.  
  2208.         /* get the data out */
  2209.         {
  2210.             largefixedsigned*            DataBlock;
  2211.             WaveTableStorDispRec*    NewWaveTable;
  2212.             long                                    TableScan;
  2213.             long                                    FrameScan;
  2214.  
  2215.             DataBlock = (largefixedsigned*)GetStackArray(ParamList,3);
  2216.             CheckPtrExistence((char*)DataBlock);
  2217.             NewWaveTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(
  2218.                 Window->WaveTableData),TotalFramesPerTable);
  2219.             if (NewWaveTable == NIL)
  2220.                 {
  2221.                  FinishedSideNoMemory1:
  2222.                     AlertHalt("There is not enough memory available to build the wave.",NIL);
  2223.                     DisposeParamStack(ParamList);
  2224.                     DisposePcode(FuncCode);
  2225.                     return;
  2226.                 }
  2227.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2228.                 {
  2229.                     if (!WaveTableStorDispAppendEntry(NewWaveTable))
  2230.                         {
  2231.                          FinishedSideNoMemory2:
  2232.                             DisposeWaveTableStorDisp(NewWaveTable);
  2233.                             goto FinishedSideNoMemory1;
  2234.                         }
  2235.                 }
  2236.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2237.                 {
  2238.                     for (FrameScan = 0; FrameScan < TotalFramesPerTable; FrameScan += 1)
  2239.                         {
  2240.                             PRNGCHK(DataBlock,&(DataBlock[TableScan * TotalFramesPerTable + FrameScan]),
  2241.                                 sizeof(DataBlock[TableScan * TotalFramesPerTable + FrameScan]));
  2242.                             WaveTableStorDispSetFrame(NewWaveTable,TableScan,FrameScan,
  2243.                                 DataBlock[TableScan * TotalFramesPerTable + FrameScan]);
  2244.                         }
  2245.                 }
  2246.             Window->UndoBackupWaveTable = Window->WaveTableData;
  2247.             Window->WaveTableData = NewWaveTable;
  2248.             Window->WaveDataModified = True;
  2249.         }
  2250.         DisposeParamStack(ParamList); /* disposes our array for us */
  2251.         DisposePcode(FuncCode);
  2252.         WaveTableWindowUpdateAllParameters(Window);
  2253.     }
  2254.  
  2255.  
  2256. /* get a copy of the wave data array */
  2257. largefixedsigned*        WaveTableWindowGetWaveArray(WaveTableWindowRec* Window)
  2258.     {
  2259.         largefixedsigned*    Array;
  2260.         long                            TableLimit;
  2261.         long                            FrameLimit;
  2262.         long                            TableScan;
  2263.  
  2264.         CheckPtrExistence(Window);
  2265.         TableLimit = WaveTableStorDispNumTables(Window->WaveTableData);
  2266.         FrameLimit = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  2267.         Array = (largefixedsigned*)AllocPtrCanFail(TableLimit * FrameLimit
  2268.             * sizeof(largefixedsigned),"WaveTableWindowGetWaveArray");
  2269.         if (Array != NIL)
  2270.             {
  2271.                 for (TableScan = 0; TableScan < TableLimit; TableScan += 1)
  2272.                     {
  2273.                         long                            FrameScan;
  2274.  
  2275.                         for (FrameScan = 0; FrameScan < FrameLimit; FrameScan += 1)
  2276.                             {
  2277.                                 PRNGCHK(Array,&(Array[TableScan * FrameLimit + FrameScan]),
  2278.                                     sizeof(Array[TableScan * FrameLimit + FrameScan]));
  2279.                                 Array[TableScan * FrameLimit + FrameScan]
  2280.                                     = WaveTableStorDispGetFrame(Window->WaveTableData,
  2281.                                     TableScan,FrameScan);
  2282.                             }
  2283.                     }
  2284.             }
  2285.         return Array;
  2286.     }
  2287.  
  2288.  
  2289. /* force the wave data to be written back to the object.  this does not write back */
  2290. /* any other data. */
  2291. MyBoolean                        WaveTableWindowForceWaveTableUpdate(WaveTableWindowRec* Window)
  2292.     {
  2293.         WaveTableStorageRec*        NewWaveTable;
  2294.  
  2295.         CheckPtrExistence(Window);
  2296.  
  2297.         NewWaveTable = NewWaveTableStorage(WaveTableStorDispNumBits(Window->WaveTableData),
  2298.             WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  2299.         if (NewWaveTable != NIL)
  2300.             {
  2301.                 long                                        Limit;
  2302.                 long                                        Scan;
  2303.  
  2304.                 Limit = WaveTableStorDispNumTables(Window->WaveTableData);
  2305.                 for (Scan = 0; Scan < Limit; Scan += 1)
  2306.                     {
  2307.                         long                            Index;
  2308.                         long                            IndexLimit;
  2309.  
  2310.                         if (!WaveTableStorageAppendEntry(NewWaveTable))
  2311.                             {
  2312.                                 DisposeWaveTableStorage(NewWaveTable);
  2313.                                 return False;
  2314.                             }
  2315.                         IndexLimit = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  2316.                         for (Index = 0; Index < IndexLimit; Index += 1)
  2317.                             {
  2318.                                 WaveTableStorageSetFrame(NewWaveTable,Scan,Index,
  2319.                                     WaveTableStorDispGetFrame(Window->WaveTableData,Scan,Index));
  2320.                             }
  2321.                     }
  2322.                 WaveTableObjectPutNewData(Window->WaveTableObject,NewWaveTable);
  2323.                 return True;
  2324.             }
  2325.          else
  2326.             {
  2327.                 return False;
  2328.             }
  2329.     }
  2330.  
  2331.  
  2332. /* force all data to be written back to the object.  this includes calling */
  2333. /* WaveTableWindowForceWaveTableUpdate() */
  2334. MyBoolean                        WaveTableWindowWritebackModifiedData(WaveTableWindowRec* Window)
  2335.     {
  2336.         MyBoolean                    SuccessFlag = True;
  2337.  
  2338.         CheckPtrExistence(Window);
  2339.  
  2340.         if (TextEditDoesItNeedToBeSaved(Window->NameEdit))
  2341.             {
  2342.                 char*                        String;
  2343.  
  2344.                 String = WaveTableWindowGetNameCopy(Window);
  2345.                 if (String != NIL)
  2346.                     {
  2347.                         WaveTableObjectNewName(Window->WaveTableObject,String);
  2348.                         TextEditHasBeenSaved(Window->NameEdit);
  2349.                     }
  2350.                  else
  2351.                     {
  2352.                         SuccessFlag = False;
  2353.                     }
  2354.             }
  2355.  
  2356.         if (TextEditDoesItNeedToBeSaved(Window->FunctionEdit))
  2357.             {
  2358.                 char*                        String;
  2359.  
  2360.                 String = WaveTableWindowGetFormulaCopy(Window);
  2361.                 if (String != NIL)
  2362.                     {
  2363.                         WaveTableObjectNewFormula(Window->WaveTableObject,String);
  2364.                         TextEditHasBeenSaved(Window->FunctionEdit);
  2365.                     }
  2366.                  else
  2367.                     {
  2368.                         SuccessFlag = False;
  2369.                     }
  2370.             }
  2371.  
  2372.         if (TextEditDoesItNeedToBeSaved(Window->TestAttackDuration))
  2373.             {
  2374.                 char*                        String;
  2375.  
  2376.                 String = TextEditGetRawData(Window->TestAttackDuration,SYSTEMLINEFEED);
  2377.                 if (String != NIL)
  2378.                     {
  2379.                         SetWaveTableObjectTestAttack(Window->WaveTableObject,
  2380.                             StringToLongDouble(String,PtrSize(String)));
  2381.                         ReleasePtr(String);
  2382.                         TextEditHasBeenSaved(Window->TestAttackDuration);
  2383.                     }
  2384.                  else
  2385.                     {
  2386.                         SuccessFlag = False;
  2387.                     }
  2388.             }
  2389.  
  2390.         if (TextEditDoesItNeedToBeSaved(Window->TestDecayDuration))
  2391.             {
  2392.                 char*                        String;
  2393.  
  2394.                 String = TextEditGetRawData(Window->TestDecayDuration,SYSTEMLINEFEED);
  2395.                 if (String != NIL)
  2396.                     {
  2397.                         SetWaveTableObjectTestDecay(Window->WaveTableObject,
  2398.                             StringToLongDouble(String,PtrSize(String)));
  2399.                         ReleasePtr(String);
  2400.                         TextEditHasBeenSaved(Window->TestDecayDuration);
  2401.                     }
  2402.                  else
  2403.                     {
  2404.                         SuccessFlag = False;
  2405.                     }
  2406.             }
  2407.  
  2408.         if (TextEditDoesItNeedToBeSaved(Window->TestFrequency))
  2409.             {
  2410.                 char*                        String;
  2411.  
  2412.                 String = TextEditGetRawData(Window->TestFrequency,SYSTEMLINEFEED);
  2413.                 if (String != NIL)
  2414.                     {
  2415.                         SetWaveTableObjectTestPitch(Window->WaveTableObject,
  2416.                             StringToLongDouble(String,PtrSize(String)));
  2417.                         ReleasePtr(String);
  2418.                         TextEditHasBeenSaved(Window->TestFrequency);
  2419.                     }
  2420.                  else
  2421.                     {
  2422.                         SuccessFlag = False;
  2423.                     }
  2424.             }
  2425.  
  2426.         if (TextEditDoesItNeedToBeSaved(Window->TestSamplingRate))
  2427.             {
  2428.                 char*                        String;
  2429.  
  2430.                 String = TextEditGetRawData(Window->TestSamplingRate,SYSTEMLINEFEED);
  2431.                 if (String != NIL)
  2432.                     {
  2433.                         SetWaveTableObjectTestSamplingRate(Window->WaveTableObject,
  2434.                             StringToInteger(String,PtrSize(String)));
  2435.                         ReleasePtr(String);
  2436.                         TextEditHasBeenSaved(Window->TestSamplingRate);
  2437.                     }
  2438.                  else
  2439.                     {
  2440.                         SuccessFlag = False;
  2441.                     }
  2442.             }
  2443.  
  2444.         if (Window->WaveDataModified)
  2445.             {
  2446.                 if (WaveTableWindowForceWaveTableUpdate(Window))
  2447.                     {
  2448.                         Window->WaveDataModified = False;
  2449.                     }
  2450.                  else
  2451.                     {
  2452.                         SuccessFlag = False;
  2453.                     }
  2454.             }
  2455.  
  2456.         return SuccessFlag;
  2457.     }
  2458.