⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmdsmidi.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
   FIMIDISegState := nil;

   FmtStart       := 0;
   FmtOffset      := 0;
   FrtStart       := 0;
   FrtOffset      := 0;

   FTimer         := TTimer.Create(Self);
   FTimer.Enabled := False;
   FTimer.OnTimer := DoTimer;
   FTimer.Interval:= 250;

   ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
   if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
end;

{------------------------------------------------------------------------------}
destructor TMMDSMidiChannel.Destroy;
begin
   Close;

   if FMixer <> nil then FMixer.Close;

   F3DBuffer.Free;

   inherited Destroy;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.Loaded;
begin
   inherited Loaded;

   with Sound3D do
   if MM3DVectorEqual(ConeOrientation.AsVector,ZeroVector) then
      ConeOrientation.AsVector := MM3DVector(defConeOrientX,defConeOrientY,defConeOrientZ);
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.Notification(AComponent: TComponent; Operation: TOperation);
begin
   inherited Notification(AComponent, Operation);

   if (Operation = opRemove) and (AComponent = FMixer) then FMixer := nil;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.Set3DBuffer(Value: TMMDS3DBuffer);
begin
    F3DBuffer.Assign(Value);
end;

{------------------------------------------------------------------------------}
function TMMDSMidiChannel.GetDirectSound: IDirectSound;
begin
   Result := nil;

   if (FMixer <> nil) then
   begin
      Result := FMixer.DirectSound;
   end;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.SetFileName(aValue: string);
begin
   if (aValue <> FFileName) then
   begin
      FFileName := aValue;
      Close;
   end;
end;

{------------------------------------------------------------------------------}
function TMMDSMidiChannel.Open: Boolean;
var
   S: string;
   wfxsize: DWORD;

begin
   Result := False;
   if not FOpen and (FFileName <> '') then
   begin
      try
         if (FMixer <> nil) then FMixer.Open;

         // DirectMusic initialization
         FIMusic := CreateDirectMusic(DirectSound);
         if (FIMusic <> nil) then
         begin
            FIPerf := CreatePerformance(FIMusic,DirectSound);
            if (FIPerf <> nil) then
            begin
               FIPort := CreateMusicPort(FIMusic);

               FIPerf.AddPort(FIPort);
               if (FIPort <> nil) and (FMixer <> nil) then
               begin
                   FIPerf.AssignPChannelBlock(0, FIPort, 1);
                   wfxsize := sizeOf(FWaveFormat);
                   if FIPort.GetFormat(@FWaveFormat,wfxsize, FBufferLength) = S_OK then
                   begin
                      FMixer.CreateSoundBuffer(@FWaveFormat, FBufferLength, FSoundBuffer, False);
                      FIPort.SetDirectSound(DirectSound,FSoundBuffer.SoundBuffer);
                   end;
                   // Activate the synthesizer port
	           FIPort.Activate(True);
               end;

               FILoader := CreateLoader;
               if (FILoader <> nil) then
               begin
                  FIMIDIseg := LoadSegment(FILoader,FFileName);
                  if (FIMIDIseg <> nil) then
                  begin
                     S := UpperCase(ExtractFileExt(FFileName));
                     if (S = '.MID') or (S = '.RMI') then
                     begin
                        FIMIDIseg.SetParam(GUID_StandardMIDIFile,$FFFFFFFF, 0, 0, Pointer(FIPerf));
                     end;
                     FIMIDIseg.SetParam(GUID_Download, $FFFFFFFF, 0, 0, Pointer(FIPerf));
                     Result := True;
                  end;
               end;
            end;
         end;

      finally
         if not Result then
         begin
            FIMIDIseg  := nil;
            FILoader   := nil;
            FIPerf     := nil;
            FIPort     := nil;
            FIMusic    := nil;
         end
         else FOpen := True;
      end;
   end;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.Close;
begin
   if FOpen then
   begin
      Stop;
      FOpen     := False;

      if (FMixer <> nil) then FMixer.ClearBuffer(FSoundBuffer);

      if (FIMusic <> nil) then FIMusic.Activate(False);

      if (FIPerf <> nil) then FIPerf.CloseDown;

      FIPort    := nil;
      FIPerf    := nil;
      FIMIDIseg := nil;
      FILoader  := nil;
      FIMusic   := nil;

      CoUninitialize;
   end;
end;

{------------------------------------------------------------------------------}
function TMMDSMidiChannel.Play: Boolean;
begin
   Result := False;
   if not FOpen then Open;
   if FOpen and not FPlaying then
   begin
      if (FIPerf <> nil) then
      begin
         if (FLoops < 0) then FLoops := 0;
         FIMIDISeg.SetRepeats(FLoops);
         if FIPerf.PlaySegment(FIMIDISeg, DMUS_SEGF_BEAT, 0, nil) = S_OK then
         begin
            Result   := True;
            FPlaying := True;
            FTimer.Enabled := True;
         end;
      end;
   end;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.Stop;
begin
   if FPlaying then
   begin
      FIPerf.Stop(nil, nil, 0, 0);
      FPlaying := False;
      FTimer.Enabled := False;
      if not (csDestroying in ComponentState) and
         assigned(FOnplayEnd) then FOnPlayEnd(Self);
   end;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.DoTimer(Sender: TObject);
begin
   if FOpen and FPlaying and FTimer.Enabled then
   begin
      if (FIPerf.IsPlaying(FIMIDISeg,nil) <> S_OK) then
      begin
         Stop;
      end;
   end;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.SetVolume(aValue: Longint);
begin
   FSoundBuffer.Volume := aValue;
end;

{------------------------------------------------------------------------------}
function TMMDSMidiChannel.GetVolume: Longint;
begin
   Result := FSoundBuffer.Volume;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.SetPanning(aValue: Longint);
begin
   FSoundBuffer.Panning := aValue;
end;

{------------------------------------------------------------------------------}
function TMMDSMidiChannel.GetPanning: Longint;
begin
   Result := FSoundBuffer.Panning;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.SetMuted(aValue: Boolean);
begin
   FSoundBuffer.Muted := aValue;
end;

{------------------------------------------------------------------------------}
function TMMDSMidiChannel.GetMuted: Boolean;
begin
   Result := FSoundBuffer.Muted;
end;

{------------------------------------------------------------------------------}
procedure TMMDSMidiChannel.GetVUMeter(var LeftValue, RightValue, BothValue: integer; Interval: integer);
var
   dwPlayPos,dwLen1,dwLen2: DWORD;
   lpWrite1,lpWrite2: PChar;
   PeakLeft,PeakRight: Smallint;
   PeakLeft2,PeakRight2: Smallint;
   VolLeft,VolRight: Longint;

begin
   LeftValue  := 0;
   RightValue := 0;
   BothValue  := 0;

   if (FFileName <> '') and (FSoundBuffer.SoundBuffer <> nil) and
      IsPlaying and {TODO: not Paused and }not Muted then
   begin
      PeakLeft := -1;
      PeakRight:= -1;

      dwPlayPos := FSoundBuffer.Position;

      { lock the buffer }
      if FSoundBuffer.SoundBuffer.Lock(dwPlayPos, 4412, lpWrite1, dwLen1, lpWrite2, dwLen2, 0) = DS_OK then
      begin
         pcmFindPeak(@FWaveFormat, lpWrite1, dwLen1, PeakLeft, PeakRight);

         if (dwLen2 > 0) then
         begin
            pcmFindPeak(@FWaveFormat, lpWrite2, dwLen2, PeakLeft2, PeakRight2);
            if abs(PeakLeft2) > abs(PeakLeft) then PeakLeft := PeakLeft2;
            if abs(PeakRight2) > abs(PeakRight) then PeakRight := PeakRight2;
         end;

         { unlock the buffer }
         FSoundBuffer.Soundbuffer.Unlock(lpWrite1, dwLen1, lpWrite2, dwLen2);
      end;

      if (PeakLeft <> -1) and (PeakRight <> -1) then
      begin
         if (FWaveFormat.wBitsPerSample = 8) then
         begin
            PeakLeft := (PeakLeft -128)*255;
            PeakRight:= (PeakRight-128)*255;
         end;

         CalcVolume(2*VOLUMEBASE,
                    DBToVolume(Volume/100,VOLUMEBASE),
                    RangeScale(Panning, DSBPAN_LEFT, DSBPAN_RIGHT, -32768, 32768),
                    VolLeft,VolRight);

         LeftValue := MulDiv(PeakLeft,VolLeft,VOLUMEBASE);
         RightValue := MulDiv(PeakRight,VolRight,VOLUMEBASE);

         if (abs(LeftValue) > abs(RightValue)) then
             BothValue := LeftValue
         else
             BothValue := RightValue;
      end;
   end;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -