MMFXGen.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:34k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMFXGen;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinTypes,
  33.     WinProcs,
  34. {$ENDIF}
  35.     SysUtils,
  36.     Messages,
  37.     Classes,
  38.     Controls,
  39.     Forms,
  40.     MMSystem,
  41.     MMObj,
  42.     MMDSPObj,
  43.     MMUtils,
  44.     MMString,
  45.     MMRegs,
  46.     MMPCMSup,
  47.     MMMulDiv;
  48. const
  49.     {$IFDEF CBUILDER3} {$EXTERNALSYM TabLen} {$ENDIF}
  50.     TabLen = 100000;                { precalc table length                 }
  51. type
  52.   EMMGeneratorError = class(Exception);
  53.   TMMWaveForm       = (wfSine,wfSquare,wfTriangle,wfSawtoothPos,
  54.                        wfSawtoothNeg,wfNoise);
  55.   TMMModulation     = (moAM,moFM,moPM);
  56.   {-- TMMGenerator ------------------------------------------------------}
  57.   TMMGenerator = class(TMMDSPComponent)
  58.   private
  59.     FOpen        : Boolean;
  60.     FEnabled     : Boolean;
  61.     FSilence     : SmallInt;      { silence value 0 or 128               }
  62.     FBits        : TMMBits;       { bit8 or bit16                        }
  63.     FChannel     : TMMChannel;    { chBoth, chLeft or chRigth            }
  64.     FMode        : TMMMode;       { mMono or mStereo                     }
  65.     FSampleRate  : Longint;       { samplerate 8000..88200               }
  66.     FBytesDone   : Longint;       { how many bytes created ?             }
  67.     FWaveForm    : TMMWaveForm;   { type of waveform to generate         }
  68.     FModulation  : TMMModulation; { Modulation: moAM,moFM,mpPM           }
  69.     FFrequency   : Double;        { test frequency (1..44100.00)         }
  70.     FAmplitude   : TMMVolumeRange;{ generator/modulator amplitude        }
  71.     FDryAmplitude: TMMVolumeRange;{ mix of original data mixed to output }
  72.     FWaveFormat  : TWaveFormatEx; { internal WaveFormatEx                }
  73.     FTable       : PSmallArray;
  74.     FOffset      : Double;        { internal table offset                }
  75.     procedure SetWaveForm(aValue: TMMWaveForm);
  76.     procedure SetModulation(aValue: TMMModulation);
  77.     procedure SetFrequency(aValue: Double);
  78.     procedure SetAmplitudes(index: integer; aValue: TMMVolumeRange);
  79.     procedure SetSampleRate(Rate: Longint);
  80.     procedure SetBits(aValue: TMMBits);
  81.     procedure SetChannel(aValue: TMMChannel);
  82.     procedure SetMode(aValue: TMMMode);
  83.     procedure SetWaveParams;
  84.     procedure FillWaveTable(Len: Longint);
  85.   protected
  86.     procedure ChangeDesigning(aValue: Boolean); override;
  87.     procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  88.     procedure Opened; override;
  89.     procedure Started; override;
  90.     procedure Closed; override;
  91.     procedure BufferReady(lpwh: PWaveHdr); override;
  92.     procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
  93.   public
  94.     constructor Create(AOwner:TComponent); override;
  95.     destructor  Destroy; override;
  96.     procedure Open;
  97.     procedure Start;
  98.     procedure Stop;
  99.     procedure Close;
  100.     procedure GenerateData(Buffer: PChar; NumBytes: Cardinal);
  101.     procedure ModulateDataAM(Buffer: PChar; NumBytes: Cardinal);
  102.     procedure ModulateDataFM(Buffer: PChar; NumBytes: Cardinal);
  103.     procedure ModulateDataPM(Buffer: PChar; NumBytes: Cardinal);
  104.   published
  105.     property Input;
  106.     property Output;
  107.     property Enabled: Boolean read FEnabled write FEnabled default True;
  108.     property SampleRate: Longint read FSampleRate write SetSampleRate default 11025;
  109.     property BitLength: TMMBits read FBits write setBits default b8bit;
  110.     property Channel: TMMChannel read FChannel write setChannel default chBoth;
  111.     property Mode: TMMMode read FMode write SetMode default mMono;
  112.     property WaveForm: TMMWaveForm read FWaveForm write SetWaveForm default wfSine;
  113.     property Modulation: TMMModulation read FModulation write SetModulation default moAM;
  114.     property Frequency: Double read FFrequency write SetFrequency;
  115.     property Amplitude: TMMVolumeRange index 0 read FAmplitude write SetAmplitudes default 16384;
  116.     property DryAmplitude: TMMVolumeRange index 1 read FDryAmplitude write SetAmplitudes default 0;
  117.   end;
  118. implementation
  119. uses MMMath;
  120. {-- Sine ----------------------------------------------------------------}
  121. function Sine(t: Float): Float; Far;
  122. begin
  123.    Result := Sin(t);
  124. end;
  125. {-- Square ----------------------------------------------------------------}
  126. function Square(t: Float): FLoat; Far;
  127. begin
  128.    { Compute values of t normalized to 2*pi }
  129.    t := ModR(t,2*M_PI);
  130.    { The actual square wave computation }
  131.    Result := 2*ModR(ord(t>M_PI)+1,2)-1;
  132. end;
  133. {-- SawtoothPos -----------------------------------------------------------}
  134. function SawtoothPos(t: Float): Float; Far;
  135. begin
  136.    Result := 2*(ModR(t,2*M_PI)/2/M_PI - 0.5);
  137. end;
  138. {-- SawtoothNeg -----------------------------------------------------------}
  139. function SawtoothNeg(t: Float): Float; Far;
  140. begin
  141.    Result := 2*(1-ModR(t,2*M_PI)/2/M_PI - 0.5);
  142. end;
  143. {-- Triangle --------------------------------------------------------------}
  144. function Triangle(t: Float): Float; Far;
  145. var
  146.    rt: Float;
  147. begin
  148.    rt := ModR(t+M_PI/2,2*M_PI)/2/M_PI;
  149.    if (rt < 0.5) then Result := 4*(rt-0.25)
  150.    else Result := 4*(-rt+0.75);
  151. end;
  152. {-- Noise ----------------------------------------------------------------}
  153. function Noise(t: Float): Float; Far;
  154. begin
  155.    Result := 2*(Random-0.5);
  156. end;
  157. {-- VCO ------------------------------------------------------------------}
  158. function vco(x: Float; Fc, Fs: Longint; t: Float): FLoat;
  159. var
  160.    kf: Float;
  161. begin
  162.    kf := (Fc/Fs)*2*M_PI;
  163.    Result := cos(2*M_PI*Fc*t + kf*x);
  164. end;
  165. {== TMMGenerator =========================================================}
  166. constructor TMMGenerator.Create(AOwner: TComponent);
  167. begin
  168.    inherited Create(AOwner);
  169.    FTable := nil;
  170.    FEnabled := True;
  171.    FSampleRate := 11025;
  172.    FBits := b8Bit;
  173.    FChannel := chBoth;
  174.    FMode := mMono;
  175.    FWaveForm:= wfSine;
  176.    FModulation := moAM;
  177.    FFrequency := 1000.0;
  178.    FAmplitude := 16384;
  179.    FDryAmplitude := 0;
  180.    FBytesDone := 0;
  181.    FSilence := 128;
  182.    FOpen := False;
  183.    Randomize;
  184.    SetWaveParams;
  185.    if not (csDesigning in ComponentState) then
  186.    begin
  187.       FTable := GlobalAllocMem(TabLen*sizeOf(Smallint));
  188.    end;
  189.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  190.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  191. end;
  192. {-- TMMGenerator --------------------------------------------------------}
  193. destructor TMMGenerator.Destroy;
  194. begin
  195.    GlobalFreeMem(Pointer(FTable));
  196.    inherited Destroy;
  197. end;
  198. {-- TMMGenerator --------------------------------------------------------}
  199. procedure TMMGenerator.ChangeDesigning(aValue: Boolean);
  200. begin
  201.    inherited ChangeDesigning(aValue);
  202.    if not (csDesigning in ComponentState) then
  203.    begin
  204.       FTable := GlobalAllocMem(TabLen*sizeOf(Smallint));
  205.    end;
  206. end;
  207. {-- TMMGenerator --------------------------------------------------------}
  208. procedure TMMGenerator.FillWaveTable(Len: Longint);
  209. var
  210.    i: Longint;
  211.    amp: integer;
  212.    pt: PSmallint;
  213. begin
  214.    { TODO: Wenn Table > 140k dann laufen die Multiplikationen 黚er }
  215.    { TODO: Table Gr鰏se als power of 2 und mit AND wrappen         }
  216.    if not FOpen then exit;
  217.    if FBits = b8Bit then
  218.       amp := 127
  219.    else
  220.       amp := 32767;
  221.    pt := PSmallint(FTable);
  222.    case FWaveForm of
  223.      wfSine:
  224.      for i := 0 to Len-1 do
  225.      begin
  226.         pt^ := Round(amp*sin(i*2*M_PI/Len));
  227.         incHuge(pt,sizeOf(pt^));
  228.      end;
  229.      wfSquare:
  230.      for i := 0 to Len-1 do
  231.      begin
  232.         if i > Len div 2 then
  233.            pt^ := amp
  234.         else
  235.            pt^ := -amp;
  236.         incHuge(pt,sizeOf(pt^));
  237.      end;
  238.      wfTriangle:
  239.      for i := 0 to Len-1 do
  240.      begin
  241.         if i <= Len div 4 then
  242.            pt^ := i*amp div (Len div 4)
  243.         else if i > 3*(Len div 4) then
  244.            pt^ := (i-3*(Len div 4))*amp div (Len div 4) - amp
  245.         else
  246.            pt^ := (Len div 2-i)*amp div (Len div 4);
  247.         incHuge(pt,sizeOf(pt^));
  248.      end;
  249.      wfSawtoothPos:
  250.      for i := 0 to Len-1 do
  251.      begin
  252.         if i <= Len div 2 then
  253.            pt^ := (i*amp) div (Len div 2)
  254.         else
  255.            pt^ := (i-Len div 2)*amp div (Len div 2) - amp;
  256.         incHuge(pt,sizeOf(pt^));
  257.      end;
  258.      wfSawtoothNeg:
  259.      for i := 0 to Len-1 do
  260.      begin
  261.         if i <= Len div 2 then
  262.            pt^ := -(i*amp) div (Len div 2)
  263.         else
  264.            pt^ := -((i-Len div 2)*amp div (Len div 2) - amp);
  265.         incHuge(pt,sizeOf(pt^));
  266.      end;
  267.      wfNoise:
  268.      for i := 0 to Len-1 do
  269.      begin
  270.         pt^ := Random(2*amp)-amp;
  271.         incHuge(pt,sizeOf(pt^));
  272.      end;
  273.    end;
  274. end;
  275. {-- TMMGenerator --------------------------------------------------------}
  276. Procedure TMMGenerator.SetPWaveFormat(aValue: PWaveFormatEx);
  277. begin
  278.    if (aValue <> nil) then
  279.    begin
  280.       if not (csDesigning in ComponentState) then
  281.          if not pcmIsValidFormat(aValue) then
  282.             raise EMMGeneratorError.Create(LoadResStr(IDS_INVALIDFORMAT));
  283.       SampleRate := aValue^.nSamplesPerSec;
  284.       BitLength := TMMBits(aValue^.wBitsPerSample div 8 - 1);
  285.       Mode := TMMMode(aValue^.nChannels-1);
  286.       FillWaveTable(TabLen);
  287.    end;
  288.    inherited SetPWaveFormat(aValue);
  289. end;
  290. {-- TMMGenerator --------------------------------------------------------}
  291. procedure TMMGenerator.SetWaveParams;
  292. begin
  293.    pcmBuildWaveHeader(@FWaveFormat,(Ord(FBits)+1)*8,Ord(FMode)+1,FSampleRate);
  294.    PWaveFormat := @FWaveFormat;
  295. end;
  296. {-- TMMGenerator --------------------------------------------------------}
  297. Procedure TMMGenerator.SetSampleRate(Rate: Longint);
  298. begin
  299.      if (Rate <> SampleRate) then
  300.      begin
  301.         FSampleRate := MinMax(Rate,8000,88200);
  302.         SetWaveParams;
  303.      end;
  304. end;
  305. {-- TMMGenerator --------------------------------------------------------}
  306. Procedure TMMGenerator.SetBits(aValue: TMMBits);
  307. begin
  308.    if (aValue <> FBits) then
  309.    begin
  310.       FBits := aValue;
  311.       if (FBits = b8Bit) then
  312.           FSilence := 128
  313.       else
  314.           FSilence := 0;
  315.       SetWaveParams;
  316.    end;
  317. end;
  318. {-- TMMGenerator --------------------------------------------------------}
  319. Procedure TMMGenerator.SetChannel(aValue: TMMChannel);
  320. begin
  321.    if (aValue <> FChannel) then
  322.    begin
  323.       FChannel := aValue;
  324.    end;
  325. end;
  326. {-- TMMGenerator --------------------------------------------------------}
  327. Procedure TMMGenerator.SetMode(aValue: TMMMode);
  328. begin
  329.    if (aValue <> FMode) and (aValue in [mMono,mStereo]) then
  330.    begin
  331.       FMode := aValue;
  332.       SetWaveParams;
  333.    end;
  334.    {$IFDEF WIN32}
  335.    {$IFDEF TRIAL}
  336.    {$DEFINE _HACK1}
  337.    {$I MMHACK.INC}
  338.    {$ENDIF}
  339.    {$ENDIF}
  340. end;
  341. {-- TMMGenerator --------------------------------------------------------}
  342. procedure TMMGenerator.SetWaveForm(aValue: TMMWaveForm);
  343. begin
  344.    if (aValue <> FWaveForm) then
  345.    begin
  346.       FWaveForm := aValue;
  347.       FillWaveTable(TabLen);
  348.    end;
  349.    {$IFDEF WIN32}
  350.    {$IFDEF TRIAL}
  351.    {$DEFINE _HACK2}
  352.    {$I MMHACK.INC}
  353.    {$ENDIF}
  354.    {$ENDIF}
  355. end;
  356. {-- TMMGenerator --------------------------------------------------------}
  357. procedure TMMGenerator.SetModulation(aValue: TMMModulation);
  358. begin
  359.    if (aValue <> FModulation) then
  360.    begin
  361.       FModulation := aValue;
  362.    end;
  363.    {$IFDEF WIN32}
  364.    {$IFDEF TRIAL}
  365.    {$DEFINE _HACK3}
  366.    {$I MMHACK.INC}
  367.    {$ENDIF}
  368.    {$ENDIF}
  369. end;
  370. {-- TMMGenerator --------------------------------------------------------}
  371. procedure TMMGenerator.SetFrequency(aValue: Double);
  372. begin
  373.    if (aValue <> FFrequency) then
  374.    begin
  375.       FFrequency := MinMaxR(aValue,0.01,100000);
  376.    end;
  377. end;
  378. {-- TMMGenerator --------------------------------------------------------}
  379. procedure TMMGenerator.SetAmplitudes(index: integer; aValue: TMMVolumeRange);
  380. begin
  381.    case Index of
  382.       0: if (aValue = FAmplitude) then exit else FAmplitude := aValue;
  383.       1: if (aValue = FDryAmplitude) then exit else FDryAmplitude := aValue;
  384.    end;
  385. end;
  386. {-- TMMGenerator --------------------------------------------------------}
  387. procedure TMMGenerator.GenerateData(Buffer: PChar; NumBytes: Cardinal);
  388. type
  389.    TGetSample = function: Smallint;
  390. var
  391.    i,ReIndex: integer;
  392.    pS: PSmallint;
  393.    pB: PByte;
  394.    Step: Double;
  395.    function GetSample: Smallint;
  396.    {$IFNDEF WIN32}
  397.    var
  398.       pt: PSmallint;
  399.    {$ENDIF}
  400.    begin
  401.       {$IFDEF WIN32}
  402.       Result := MulDiv32(FTable^[Round(FOffset)],FAmplitude,VOLUMEBASE);
  403.       {$ELSE}
  404.       pt := Pointer(FTable);
  405.       incHuge(pt, Round(FOffset)*sizeOf(pt^));
  406.       Result := MulDiv32(pt^,FAmplitude,VOLUMEBASE);
  407.       {$ENDIF}
  408.       FOffset := ModR(FOffset+Step,TabLen-1);
  409.    end;
  410. begin
  411.    ReIndex := Ord(FChannel)-1;
  412.    Step    := FFrequency*TabLen/FSampleRate;
  413.    if (FBits = b8bit) then
  414.    begin
  415.       pB := PByte(Buffer);
  416.       if (FMode = mMono) then
  417.       begin
  418.          for i := 0 to NumBytes-1 do
  419.          begin
  420.             pB^ := GetSample+128;
  421.             inc(pB);
  422.          end;
  423.       end
  424.       else if (FChannel = chBoth) then
  425.       begin
  426.          NumBytes := (NumBytes and not 1) shr 1;
  427.          for i := 0 to NumBytes-1 do
  428.          begin
  429.             pB^ := GetSample+128;
  430.             PByte(PChar(pB)+1)^ := pB^;
  431.             inc(pB,2);
  432.          end;
  433.       end
  434.       else
  435.       begin
  436.          inc(pB,ReIndex);
  437.          NumBytes := (NumBytes and not 1) shr 1;
  438.          for i := 0 to NumBytes-1 do
  439.          begin
  440.             pB^ := GetSample+128;
  441.             inc(pB,2);
  442.          end;
  443.       end;
  444.    end
  445.    else
  446.    begin
  447.       pS := PSmallInt(Buffer);
  448.       if (FMode = mMono) then
  449.       begin
  450.          NumBytes := (NumBytes and not 1) shr 1;
  451.          for i := 0 to NumBytes-1 do
  452.          begin
  453.             pS^ := GetSample;
  454.             inc(pS);
  455.          end;
  456.       end
  457.       else if (FChannel = chBoth) then
  458.       begin
  459.          NumBytes := (NumBytes and not 3) shr 2;
  460.          for i := 0 to NumBytes-1 do
  461.          begin
  462.             pS^ := GetSample;
  463.             PSmallInt(PChar(pS)+2)^ := pS^;
  464.             inc(pS,2);
  465.          end;
  466.       end
  467.       else
  468.       begin
  469.          inc(pS, ReIndex);
  470.          NumBytes := (NumBytes and not 3) shr 2;
  471.          for i := 0 to NumBytes-1 do
  472.          begin
  473.             pS^ := GetSample;
  474.             inc(pS,2);
  475.          end;
  476.       end;
  477.    end;
  478. end;
  479. {-- TMMGenerator --------------------------------------------------------}
  480. procedure TMMGenerator.ModulateDataAM(Buffer: PChar; NumBytes: Cardinal);
  481. type
  482.    TGetSample = function: Smallint;
  483. var
  484.    i,ReIndex: integer;
  485.    s: Smallint;
  486.    Dry,Wet: Longint;
  487.    pS: PSmallint;
  488.    pB: PByte;
  489.    Step: Double;
  490.    function GetSample: Smallint;
  491.    {$IFNDEF WIN32}
  492.    var
  493.       pt: PSmallint;
  494.    {$ENDIF}
  495.    begin
  496.       {$IFDEF WIN32}
  497.       Result := MulDiv32(FTable^[Round(FOffset)],FAmplitude,VOLUMEBASE);
  498.       {$ELSE}
  499.       pt := Pointer(FTable);
  500.       incHuge(pt, Round(FOffset)*sizeOf(pt^));
  501.       Result := MulDiv32(pt^,FAmplitude,VOLUMEBASE);
  502.       {$ENDIF}
  503.       FOffset := ModR(FOffset+Step,TabLen-1);
  504.    end;
  505. begin
  506.    { Amplitude Modulation: y(t) = Ac * sin(Wct) * Am * sin(Wmt) }
  507.    ReIndex := Ord(FChannel)-1;
  508.    Step    := FFrequency*TabLen/FSampleRate;
  509.    if (FBits = b8bit) then
  510.    begin
  511.       pB := PByte(Buffer);
  512.       if (FMode = mMono) then
  513.       begin
  514.          for i := 0 to NumBytes-1 do
  515.          begin
  516.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  517.             Wet := (Smallint(pB^-128)*GetSample) div 128;
  518.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  519.             inc(pB);
  520.          end;
  521.       end
  522.       else if (FChannel = chBoth) then
  523.       begin
  524.          NumBytes := (NumBytes and not 1) shr 1;
  525.          for i := 0 to NumBytes-1 do
  526.          begin
  527.             s := GetSample;
  528.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  529.             Wet := (Smallint(pB^-128)*s) div 128;
  530.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  531.             inc(pB);
  532.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  533.             Wet := ((pB^-128)*s) div 128;
  534.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  535.             inc(pB);
  536.          end;
  537.       end
  538.       else
  539.       begin
  540.          inc(pB,ReIndex);
  541.          NumBytes := (NumBytes and not 1) shr 1;
  542.          for i := 0 to NumBytes-1 do
  543.          begin
  544.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  545.             Wet := (Smallint(pB^-128)*GetSample) div 128;
  546.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  547.             inc(pB,2);
  548.          end;
  549.       end;
  550.    end
  551.    else
  552.    begin
  553.       pS := PSmallInt(Buffer);
  554.       if (FMode = mMono) then
  555.       begin
  556.          NumBytes := (NumBytes and not 1) shr 1;
  557.          for i := 0 to NumBytes-1 do
  558.          begin
  559.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  560.             Wet := (Longint(pS^)*GetSample) div 32768;
  561.             pS^ := pcmSampleClip16(Dry+Wet);
  562.             inc(pS);
  563.          end;
  564.       end
  565.       else if (FChannel = chBoth) then
  566.       begin
  567.          NumBytes := (NumBytes and not 3) shr 2;
  568.          for i := 0 to NumBytes-1 do
  569.          begin
  570.             s := GetSample;
  571.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  572.             Wet := (Longint(pS^)*s) div 32768;
  573.             pS^ := pcmSampleClip16(Dry+Wet);
  574.             inc(pS);
  575.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  576.             Wet := (Longint(pS^)*s) div 32768;
  577.             pS^ := pcmSampleClip16(Dry+Wet);
  578.             inc(pS);
  579.          end;
  580.       end
  581.       else
  582.       begin
  583.          inc(pS, ReIndex);
  584.          NumBytes := (NumBytes and not 3) shr 2;
  585.          for i := 0 to NumBytes-1 do
  586.          begin
  587.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  588.             Wet := (Longint(pS^)*GetSample) div 32768;
  589.             pS^ := pcmSampleClip16(Dry+Wet);
  590.             inc(pS,2);
  591.          end;
  592.       end;
  593.    end;
  594. end;
  595. {-- TMMGenerator --------------------------------------------------------}
  596. procedure TMMGenerator.ModulateDataFM(Buffer: PChar; NumBytes: Cardinal);
  597. type
  598.    TGetSample = function: Smallint;
  599. var
  600.    i: integer;
  601.    //ReIndex: integer;
  602. //   s: Smallint;
  603. //   Dry,Wet: Longint;
  604.    pS: PSmallint;
  605. //   pB: PByte;
  606. //   Step: Double;
  607.    function GetSample(s: Float): Longint;
  608.    begin
  609.       Result := MulDiv32(FTable^[Round(FOffset)],FAmplitude,VOLUMEBASE);
  610.       FOffset := ModR(FOffset+FFrequency*TabLen/FSampleRate*(1+s),TabLen-1);
  611.    end;
  612. begin
  613.    { Frequency Modulation: y(t) = Ac * sin(Wct* Am * sin(Wmt)) }
  614. //   ReIndex := Ord(FChannel)-1;
  615. //   Step    := FFrequency*TabLen/FSampleRate;
  616.    pS := PSmallInt(Buffer);
  617.    NumBytes := (NumBytes and not 1) shr 1;
  618.    for i := 0 to NumBytes-1 do
  619.    begin
  620.       { Frequency Modulation: y(t) = Ac * sin(Wct* Am * sin(Wmt)) }
  621.       pS^ := GetSample(pS^/32768);
  622.       inc(pS);
  623.    end;
  624. (*   if (FBits = b8bit) then
  625.    begin
  626.       pB := PByte(Buffer);
  627.       if (FMode = mMono) then
  628.       begin
  629.          for i := 0 to NumBytes-1 do
  630.          begin
  631.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  632.             Wet := ((pB^-128)*GetSample) div 128;
  633.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  634.             inc(pB);
  635.          end;
  636.       end
  637.       else if (FChannel = chBoth) then
  638.       begin
  639.          NumBytes := (NumBytes and not 1) shr 1;
  640.          for i := 0 to NumBytes-1 do
  641.          begin
  642.             s := GetSample;
  643.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  644.             Wet := ((pB^-128)*s) div 128;
  645.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  646.             inc(pB);
  647.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  648.             Wet := ((pB^-128)*s) div 128;
  649.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  650.             inc(pB);
  651.          end;
  652.       end
  653.       else
  654.       begin
  655.          inc(pB,ReIndex);
  656.          NumBytes := (NumBytes and not 1) shr 1;
  657.          for i := 0 to NumBytes-1 do
  658.          begin
  659.             Dry := MulDiv32(pB^-128,FDryAmplitude,VOLUMEBASE);
  660.             Wet := ((pB^-128)*GetSample) div 128;
  661.             pB^ := pcmSampleClip8(Dry+Wet)+128;
  662.             inc(pB,2);
  663.          end;
  664.       end;
  665.    end
  666.    else
  667.    begin
  668.       pS := PSmallInt(Buffer);
  669.       if (FMode = mMono) then
  670.       begin
  671.          NumBytes := (NumBytes and not 1) shr 1;
  672.          for i := 0 to NumBytes-1 do
  673.          begin
  674.             { Frequency Modulation: y(t) = Ac * sin(Wct* Am * sin(Wmt)) }
  675.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  676.             Wet := (pS^*GetSample) div 32768;
  677.             pS^ := pcmSampleClip16(Dry+Wet);
  678.             inc(pS);
  679.          end;
  680.       end
  681.       else if (FChannel = chBoth) then
  682.       begin
  683.          NumBytes := (NumBytes and not 3) shr 2;
  684.          for i := 0 to NumBytes-1 do
  685.          begin
  686.             { Frequency Modulation: y(t) = Ac * sin(Wct* Am * sin(Wmt)) }
  687.             s := GetSample;
  688.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  689.             Wet := (pS^*s) div 32768;
  690.             pS^ := pcmSampleClip16(Dry+Wet);
  691.             inc(pS);
  692.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  693.             Wet := (pS^*s) div 32768;
  694.             pS^ := pcmSampleClip16(Dry+Wet);
  695.             inc(pS);
  696.          end;
  697.       end
  698.       else
  699.       begin
  700.          inc(pS, ReIndex);
  701.          NumBytes := (NumBytes and not 3) shr 2;
  702.          for i := 0 to NumBytes-1 do
  703.          begin
  704.             Dry := MulDiv32(pS^,FDryAmplitude,VOLUMEBASE);
  705.             Wet := (pS^*GetSample) div 32768;
  706.             pS^ := pcmSampleClip16(Dry+Wet);
  707.             inc(pS,2);
  708.          end;
  709.       end;
  710.    end; *)
  711. end;
  712. (*
  713. {-- TMMGenerator --------------------------------------------------------}
  714. procedure TMMGenerator.ModulateDataFM(Buffer: PChar; NumBytes: Cardinal);
  715. var
  716.    i,amp: integer;
  717.    Time,Sample: Float;
  718.    NumSamples: Cardinal;
  719.    ReIndex: integer;
  720.    pB: PByte;
  721.    pS: PSMallInt;
  722.    FreqFactor: Float;
  723. begin
  724.    { Frequency Modulation: y(t) = Ac * sin(Wct* Am * sin(Wmt)) }
  725.    Sample := 1.0/FSampleRate;
  726.    ReIndex := Ord(FChannel)-1;
  727.    FreqFactor := 2*M_PI*FFrequency;
  728.    if (FBits = b8bit) then
  729.    begin
  730.       pB := PByte(Buffer);
  731.       Amp := Round(FAmplitude*(127/100));
  732.       if (FMode = mMono) then
  733.       begin
  734.          NumSamples := NumBytes;
  735.          Time := Sample * FBytesDone;
  736.          for i := 0 to NumSamples-1 do
  737.          begin
  738.             pB^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+((pB^-128)/12.8))+128);
  739.             inc(pB);
  740.             Time := Time + Sample;
  741.          end;
  742.          inc(FBytesDone,NumBytes);
  743.       end
  744.       else if (FChannel = chBoth) then
  745.       begin
  746.          NumBytes := NumBytes and $FFFE;
  747.          NumSamples := NumBytes shr 1;
  748.          Time := Sample * (FBytesDone shr 1);
  749.          for i := 0 to NumSamples-1 do
  750.          begin
  751.             pB^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+((pB^-128)/12.8))+128);
  752.             PByte(PChar(pB)+1)^ := pB^;
  753.             inc(pB,2);
  754.             Time := Time + Sample;
  755.          end;
  756.          inc(FBytesDone,NumBytes);
  757.       end
  758.       else
  759.       begin
  760.          inc(pB,ReIndex);
  761.          NumBytes := NumBytes and $FFFE;
  762.          NumSamples := NumBytes shr 1;
  763.          Time := Sample * (FBytesDone shr 1);
  764.          for i := 0 to NumSamples-1 do
  765.          begin
  766.             pB^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+((pB^-128)/12.8))+128);
  767.             inc(pB,2);
  768.             Time := Time + Sample;
  769.          end;
  770.          inc(FBytesDone,NumBytes);
  771.       end;
  772.    end
  773.    else
  774.    begin
  775.       pS := pSmallInt(Buffer);
  776.       Amp := Round(FAmplitude*(32767/100));
  777.       if (FMode = mMono) then
  778.       begin
  779.          NumBytes := NumBytes and $FFFE;
  780.          NumSamples := NumBytes shr 1;
  781.          Time := Sample * (FBytesDone shr 1);
  782.          for i := 0 to NumSamples-1 do
  783.          begin
  784.            { Frequency Modulation: y(t) = Ac * sin(Wct* Am * sin(Wmt)) }
  785.             pS^ := Trunc(Amp*FWaveFunc(FreqFactor*Time*(pS^/3276800)));
  786.             inc(pS);
  787.             Time := Time + Sample;
  788.          end;
  789.          inc(FBytesDone,NumBytes);
  790.       end
  791.       else if (FChannel = chBoth) then
  792.       begin
  793.          NumBytes := (NumBytes shr 2) shl 2;
  794.          NumSamples := NumBytes shr 2;
  795.          Time := Sample * (FBytesDone shr 2);
  796.          for i := 0 to NumSamples-1 do
  797.          begin
  798.             pS^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+(pS^/3276.8)));
  799.             PSmallInt(PChar(pS)+2)^ := pS^;
  800.             inc(pS,2);
  801.             Time := Time + Sample;
  802.          end;
  803.          inc(FBytesDone,NumBytes);
  804.       end
  805.       else
  806.       begin
  807.          inc(pS,ReIndex);
  808.          NumBytes := (NumBytes shr 2) shl 2;
  809.          NumSamples := NumBytes shr 2;
  810.          Time := Sample * (FBytesDone shr 2);
  811.          for i := 0 to NumSamples-1 do
  812.          begin
  813.             pS^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+(pS^/3276.8)));
  814.             inc(pS,2);
  815.             Time := Time + Sample;
  816.          end;
  817.          inc(FBytesDone,NumBytes);
  818.       end;
  819.    end;
  820. end;
  821. *)
  822. {-- TMMGenerator --------------------------------------------------------}
  823. procedure TMMGenerator.ModulateDataPM(Buffer: PChar; NumBytes: Cardinal);
  824. (*var
  825.    i,amp: integer;
  826.    Time,Sample: Float;
  827.    NumSamples: Cardinal;
  828.    ReIndex: integer;
  829.    pB: PByte;
  830.    pS: PSMallInt;
  831.    FreqFactor: Float;
  832.  *)
  833. begin
  834. (*
  835.    { Phase Modulation: y(t) = Ac * sin(Wct* Am + sin(Wmt)) }
  836.    Sample := 1.0/FSampleRate;
  837.    ReIndex := Ord(FChannel)-1;
  838.    FreqFactor := 2*M_PI*FFrequency;
  839.    if (FBits = b8bit) then
  840.    begin
  841.       pB := PByte(Buffer);
  842.       Amp := Round(FAmplitude*(127/100));
  843.       if (FMode = mMono) then
  844.       begin
  845.          NumSamples := NumBytes;
  846.          Time := Sample * FBytesDone;
  847.          for i := 0 to NumSamples-1 do
  848.          begin
  849.             pB^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+((pB^-128)/12.8))+128);
  850.             inc(pB);
  851.             Time := Time + Sample;
  852.          end;
  853.          inc(FBytesDone,NumBytes);
  854.       end
  855.       else if (FChannel = chBoth) then
  856.       begin
  857.          NumBytes := NumBytes and $FFFE;
  858.          NumSamples := NumBytes shr 1;
  859.          Time := Sample * (FBytesDone shr 1);
  860.          for i := 0 to NumSamples-1 do
  861.          begin
  862.             pB^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+((pB^-128)/12.8))+128);
  863.             PByte(PChar(pB)+1)^ := pB^;
  864.             inc(pB,2);
  865.             Time := Time + Sample;
  866.          end;
  867.          inc(FBytesDone,NumBytes);
  868.       end
  869.       else
  870.       begin
  871.          inc(pB,ReIndex);
  872.          NumBytes := NumBytes and $FFFE;
  873.          NumSamples := NumBytes shr 1;
  874.          Time := Sample * (FBytesDone shr 1);
  875.          for i := 0 to NumSamples-1 do
  876.          begin
  877.             pB^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+((pB^-128)/12.8))+128);
  878.             inc(pB,2);
  879.             Time := Time + Sample;
  880.          end;
  881.          inc(FBytesDone,NumBytes);
  882.       end;
  883.    end
  884.    else
  885.    begin
  886.       pS := pSmallInt(Buffer);
  887.       Amp := Round(FAmplitude*(32767/100));
  888.       if (FMode = mMono) then
  889.       begin
  890.          NumBytes := NumBytes and $FFFE;
  891.          NumSamples := NumBytes shr 1;
  892.          Time := Sample * (FBytesDone shr 1);
  893.          for i := 0 to NumSamples-1 do
  894.          begin
  895.             pS^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+(pS^/3276.8)));
  896.             inc(pS);
  897.             Time := Time + Sample;
  898.          end;
  899.          inc(FBytesDone,NumBytes);
  900.       end
  901.       else if (FChannel = chBoth) then
  902.       begin
  903.          NumBytes := (NumBytes shr 2) shl 2;
  904.          NumSamples := NumBytes shr 2;
  905.          Time := Sample * (FBytesDone shr 2);
  906.          for i := 0 to NumSamples-1 do
  907.          begin
  908.             pS^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+(pS^/3276.8)));
  909.             PSmallInt(PChar(pS)+2)^ := pS^;
  910.             inc(pS,2);
  911.             Time := Time + Sample;
  912.          end;
  913.          inc(FBytesDone,NumBytes);
  914.       end
  915.       else
  916.       begin
  917.          inc(pS,ReIndex);
  918.          NumBytes := (NumBytes shr 2) shl 2;
  919.          NumSamples := NumBytes shr 2;
  920.          Time := Sample * (FBytesDone shr 2);
  921.          for i := 0 to NumSamples-1 do
  922.          begin
  923.             pS^ := Trunc(Amp*FWaveFunc(FreqFactor*Time+(pS^/3276.8)));
  924.             inc(pS,2);
  925.             Time := Time + Sample;
  926.          end;
  927.          inc(FBytesDone,NumBytes);
  928.       end;
  929.    end;  *)
  930. end;
  931. {-- TMMGenerator --------------------------------------------------------}
  932. procedure TMMGenerator.Open;
  933. begin
  934.    if not FOpen then
  935.    begin
  936.       FOpen := True;
  937.       FillWaveTable(TabLen);
  938.    end;
  939. end;
  940. {-- TMMGenerator --------------------------------------------------------}
  941. procedure TMMGenerator.Start;
  942. begin
  943.    FOffset := 0;
  944. end;
  945. {-- TMMGenerator --------------------------------------------------------}
  946. procedure TMMGenerator.Stop;
  947. begin
  948.    ;
  949. end;
  950. {-- TMMGenerator --------------------------------------------------------}
  951. procedure TMMGenerator.Close;
  952. begin
  953.    if FOpen then
  954.    begin
  955.       FOpen := False;
  956.    end;
  957. end;
  958. {-- TMMGenerator --------------------------------------------------------}
  959. procedure TMMGenerator.Opened;
  960. begin
  961.    inherited Opened;
  962.    Open;
  963. end;
  964. {-- TMMGenerator --------------------------------------------------------}
  965. procedure TMMGenerator.Closed;
  966. begin
  967.    Close;
  968.    inherited Closed;
  969. end;
  970. {-- TMMGenerator --------------------------------------------------------}
  971. procedure TMMGenerator.Started;
  972. begin
  973.    inherited Started;
  974.    Start;
  975. end;
  976. {-- TMMGenerator --------------------------------------------------------}
  977. procedure TMMGenerator.BufferReady(lpwh: PWaveHdr);
  978. begin
  979.    if Enabled then
  980.    begin
  981.       if FModulation = moAM then
  982.          ModulateDataAM(lpwh^.lpData, lpwh^.dwBytesRecorded)
  983.       else if FModulation = moFM then
  984.          ModulateDataFM(lpwh^.lpData, lpwh^.dwBytesRecorded)
  985.       else
  986.          ModulateDataPM(lpwh^.lpData, lpwh^.dwBytesRecorded);
  987.    end;
  988.    inherited BufferReady(lpwh);
  989. end;
  990. {-- TMMGenerator --------------------------------------------------------}
  991. procedure TMMGenerator.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
  992. var
  993.    MustGenerate: Boolean;
  994. begin
  995.    MustGenerate := True;
  996.    if (Input <> nil) then
  997.    begin
  998.       inherited BufferLoad(lpwh, MoreBuffers);
  999.       if (lpwh^.dwBufferLength > 0) then
  1000.       begin
  1001.          MustGenerate := False;
  1002.          if Enabled then
  1003.          begin
  1004.             if FModulation = moAM then
  1005.                ModulateDataAM(lpwh^.lpData, lpwh^.dwBytesRecorded)
  1006.             else if FModulation = moFM then
  1007.                ModulateDataFM(lpwh^.lpData, lpwh^.dwBytesRecorded)
  1008.             else
  1009.                ModulateDataPM(lpwh^.lpData, lpwh^.dwBytesRecorded);
  1010.          end;
  1011.       end;
  1012.    end;
  1013.    if MustGenerate then
  1014.    begin
  1015.       if Enabled then
  1016.          GenerateData(lpwh^.lpData, lpwh^.dwBufferLength)
  1017.       else
  1018.          GlobalFillMem(lpwh^.lpData^, lpwh^.dwBufferLength, FSilence);
  1019.       lpwh^.dwBytesRecorded := lpwh^.dwBufferLength;
  1020.    end;
  1021.    MoreBuffers := True;
  1022. end;
  1023. (*
  1024. -----------------------------------------------------------
  1025. program SineMix; {$R-} {$S-} {$Q-}
  1026.     uses
  1027.         SBSample,
  1028.         CRT;
  1029.     const
  1030.         WaveLength = 32; {In samples, freq varies depending on CPU speed}
  1031.         Amplitude  = 8; {Keep it low to eliminate wave-top clipping}
  1032.     var
  1033.         Sines: array[0..WaveLength-1] of ShortInt;
  1034.         Sample: byte;
  1035.         x: word;
  1036.     procedure InitSines;
  1037.         var
  1038.             i: word;
  1039.         begin
  1040.             for i := 0 to WaveLength-1 do
  1041.                 Sines[i] := Round(Sin((2*Pi) * (i/WaveLength))*Amplitude);
  1042.         end;
  1043.     procedure ClipSample(var Sample: integer);
  1044.         begin
  1045.             if Sample > 127 then Sample := 127;
  1046.             if Sample < -128 then Sample := -128;
  1047.         end;
  1048.     procedure ProcessSample(var Sample: byte);
  1049.       {Make sure that you clip the sample so it stays in the proper range}
  1050.         var
  1051.             Temp: integer;
  1052.         begin
  1053.             Temp := Sample-128;
  1054.             {Process the sample here}
  1055.             Temp := Temp*2+Sines[x];
  1056.             ClipSample(Temp);
  1057.             Sample := Temp+128;
  1058.         end;
  1059.     begin
  1060.         ResetDSP;
  1061.         InitSines;
  1062.         x := 0;
  1063.         repeat
  1064.             Sample := GetSample;
  1065.             ProcessSample(Sample);
  1066.             OutputSample(Sample);
  1067.             Inc(x);
  1068.             x := x mod WaveLength;
  1069.         until KeyPressed; ReadKey;
  1070. *)
  1071. end.