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

📄 snd_dma.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 3 页
字号:
  s_pendingplays.next := @s_pendingplays;
  s_pendingplays.prev := @s_pendingplays;

  for i := 0 to MAX_PLAYSOUNDS - 1 do
  begin
    s_playsounds[i].prev := @s_freeplays;
    s_playsounds[i].next := s_freeplays.next;
    s_playsounds[i].prev^.next := @s_playsounds[i];
    s_playsounds[i].next^.prev := @s_playsounds[i];
  end;

  // clear all the channels
  FillChar(channels, sizeof(channels), 0);

  S_ClearBuffer();
end;

(*
==================
S_AddLoopSounds

Entities with a ->sound field will generated looped sounds
that are automatically started, stopped, and merged together
as the entities are sent to the client
==================
*)

procedure S_AddLoopSounds;
var
  i, j, num: Integer;
  sounds: array[0..MAX_EDICTS - 1] of Integer;
  left, right, left_total, right_total: Integer;
  ch: channel_p;
  sfx: sfx_p;
  sc: sfxcache_p;
  ent: entity_state_p;
begin
  if (cl_paused^.value <> 0) then
    exit;

  if (cls.state <> ca_active) then
    exit;

  if (not cl.sound_prepped) then
    exit;

  for i := 0 to cl.frame.num_entities - 1 do
  begin
    num := (cl.frame.parse_entities + i) and (MAX_PARSE_ENTITIES - 1);
    ent := @cl_parse_entities[num];
    sounds[i] := ent^.sound;
  end;

  for i := 0 to cl.frame.num_entities - 1 do
  begin
    if (sounds[i] = 0) then
      continue;

    sfx := cl.sound_precache[sounds[i]];
    if (sfx = nil) then
      continue;                         // bad sound effect
    sc := sfx^.cache;
    if (sc = nil) then
      continue;

    num := (cl.frame.parse_entities + i) and (MAX_PARSE_ENTITIES - 1);
    ent := @cl_parse_entities[num];

    // find the total contribution of all sounds of this type
    S_SpatializeOrigin(ent^.origin, 255.0, SOUND_LOOPATTENUATE,
      left_total, right_total);
    for j := i + 1 to cl.frame.num_entities - 1 do
    begin
      if (sounds[j] <> sounds[i]) then
        continue;
      sounds[j] := 0;                   // don't check this again later

      num := (cl.frame.parse_entities + j) and (MAX_PARSE_ENTITIES - 1);
      ent := @cl_parse_entities[num];

      S_SpatializeOrigin(ent^.origin, 255.0, SOUND_LOOPATTENUATE,
        left, right);
      left_total := left_total + left;
      right_total := right_total + right;
    end;

    if ((left_total = 0) and (right_total = 0)) then
      continue;                         // not audible

    // allocate a channel
    ch := S_PickChannel(0, 0);
    if (ch = nil) then
      exit;

    if (left_total > 255) then
      left_total := 255;
    if (right_total > 255) then
      right_total := 255;
    ch^.leftvol := left_total;
    ch^.rightvol := right_total;
    ch^.autosound := true;              // remove next frame
    ch^.sfx := sfx;
    ch^.pos := paintedtime mod sc^.length;
    ch^._end := paintedtime + sc^.length - ch^.pos;
  end;
end;

//=============================================================================

(*
============
S_RawSamples

Cinematic streaming and voice over network
============
*)

procedure S_RawSamples(samples, rate, width, channels: Integer; data: PByte);
var
  i, src, dst: Integer;
  scale: Single;
begin
  if (sound_started = 0) then
    exit;

  if (s_rawend < paintedtime) then
    s_rawend := paintedtime;
  scale := rate / dma.speed;

  //Com_Printf ("%d < %d < %d"#10, soundtime, paintedtime, s_rawend);
  if ((channels = 2) and (width = 2)) then
  begin
    if (scale = 1.0) then
    begin                               // optimized case
      for i := 0 to samples - 1 do
      begin
        dst := s_rawend and (MAX_RAW_SAMPLES - 1);
        Inc(s_rawend);
        s_rawsamples_[dst].left :=
          LittleShort(PSmallIntArray(data)[i * 2]) shl 8;
        s_rawsamples_[dst].right :=
          LittleShort(PSmallIntArray(data)[i * 2 + 1]) shl 8;
      end;
    end
    else
    begin
      i := 0;
      while (True) do
      begin
        src := Trunc(i * scale);
        if (src >= samples) then
          break;
        dst := s_rawend and (MAX_RAW_SAMPLES - 1);
        Inc(s_rawend);
        s_rawsamples_[dst].left :=
          LittleShort(PSmallIntArray(data)[src * 2]) shl 8;
        s_rawsamples_[dst].right :=
          LittleShort(PSmallIntArray(data)[src * 2 + 1]) shl 8;
        Inc(i);
      end;
    end;
  end
  else if ((channels = 1) and (width = 2)) then
  begin
    i := 0;
    while (True) do
    begin
      src := Trunc(i * scale);
      if (src >= samples) then
        break;
      dst := s_rawend and (MAX_RAW_SAMPLES - 1);
      Inc(s_rawend);
      s_rawsamples_[dst].left :=
        LittleShort(PSmallIntArray(data)[src]) shl 8;
      s_rawsamples_[dst].right :=
        LittleShort(PSmallIntArray(data)[src]) shl 8;
      Inc(i);
    end;
  end
  else if ((channels = 2) and (width = 1)) then
  begin
    i := 0;
    while (True) do
    begin
      src := Trunc(i * scale);
      if (src >= samples) then
        break;
      dst := s_rawend and (MAX_RAW_SAMPLES - 1);
      Inc(s_rawend);
      s_rawsamples_[dst].left :=
        PShortIntArray(data)[src * 2] shl 16;
      s_rawsamples_[dst].right :=
        PShortIntArray(data)[src * 2 + 1] shl 16;
      Inc(i);
    end;
  end
  else if ((channels = 1) and (width = 1)) then
  begin
    i := 0;
    while (True) do
    begin
      src := Trunc(i * scale);
      if (src >= samples) then
        break;
      dst := s_rawend and (MAX_RAW_SAMPLES - 1);
      Inc(s_rawend);
      s_rawsamples_[dst].left :=
        (PByteArray(data)[src] - 128) shl 16;
      s_rawsamples_[dst].right :=
        (PByteArray(data)[src] - 128) shl 16;
      Inc(i);
    end;
  end;
end;

//=============================================================================

(*
============
S_Update

Called once each time through the main loop
============
*)

procedure S_Update(const origin, _forward, right, up: vec3_t);
var
  i, total: Integer;
  ch, combine: channel_p;
label
  continue_;
begin
  if (sound_started = 0) then
    exit;

  // if the laoding plaque is up, clear everything
  // out to make sure we aren't looping a dirty
  // dma buffer while loading
  if (cls.disable_screen <> 0) then
  begin
    S_ClearBuffer;
    exit;
  end;

  // rebuild scale tables if volume is modified
  if (s_volume^.modified) then
    S_InitScaletable;

  VectorCopy(origin, listener_origin);
  VectorCopy(_forward, listener_forward);
  VectorCopy(right, listener_right);
  VectorCopy(up, listener_up);

  combine := nil;

  // update spatialization for dynamic sounds
  ch := @channels;
  for i := 0 to MAX_CHANNELS - 1 do
  begin
    if (ch^.sfx = nil) then
      goto continue_;
    if (ch^.autosound) then
    begin                               // autosounds are regenerated fresh each frame
      FillChar(ch^, sizeof(channel_t), 0);
      goto continue_;
    end;
    S_Spatialize(ch);                   // respatialize channel
    if ((ch^.leftvol = 0) and (ch^.rightvol = 0)) then
    begin
      FillChar(ch^, sizeof(channel_t), 0);
      goto continue_;
    end;
    continue_:
    inc(ch);
  end;

  // add loopsounds
  S_AddLoopSounds;

  //
  // debugging output
  //
  if (s_show^.value <> 0) then
  begin
    total := 0;
    ch := @channels;
    for i := 0 to MAX_CHANNELS - 1 do
    begin
      if ((ch^.sfx <> nil) and ((ch^.leftvol <> 0) or (ch^.rightvol <> 0))) then
      begin
        Com_Printf('%3d %3d %s'#10, [ch^.leftvol, ch^.rightvol, ch^.sfx^.name]);
        Inc(total);
      end;
      Inc(ch);
    end;
    Com_Printf('----(%d)---- painted: %d'#10, [total, paintedtime]);
  end;

  // mix some sound
  S_Update_();
end;

var
  buffers: Integer = 0;
  oldsamplepos: Integer = 0;

procedure GetSoundtime;
var
  samplepos: Integer;
  fullsamples: Integer;
begin
  fullsamples := dma.samples div dma.channels;

  // it is possible to miscount buffers if it has wrapped twice between
  // calls to S_Update.  Oh well.
  samplepos := SNDDMA_GetDMAPos();

  if (samplepos < oldsamplepos) then
  begin
    Inc(buffers);                       // buffer wrapped

    if (paintedtime > $40000000) then
    begin                               // time to chop things off to aprocedure 32 bit limits
      buffers := 0;
      paintedtime := fullsamples;
      S_StopAllSounds;
    end;
  end;
  oldsamplepos := samplepos;

  soundtime := buffers * fullsamples + samplepos div dma.channels;
end;

procedure S_Update_;
var
  endtime: Cardinal;
  samps: Integer;
begin
  if (sound_started = 0) then
    exit;

  SNDDMA_BeginPainting;

  if (dma.buffer = nil) then
    exit;

  // Updates DMA time
  GetSoundtime();

  // check to make sure that we haven't overshot
  if (paintedtime < soundtime) then
  begin
    Com_DPrintf('S_Update_ : overflow'#10, []);
    paintedtime := soundtime;
  end;

  // mix ahead of current position
  endtime := Trunc(soundtime + s_mixahead^.value * dma.speed);
  //endtime:=(soundtime + 4096) & ~4095;

   // mix to an even submission block size
  endtime := (endtime + dma.submission_chunk - 1) and
    not (dma.submission_chunk - 1);
  samps := dma.samples shr (dma.channels - 1);
  if (endtime - soundtime > samps) then
    endtime := soundtime + samps;

  S_PaintChannels(endtime);

  SNDDMA_Submit();
end;

(*
===============================================================================

console functions

===============================================================================
*)

procedure S_Play;
var
  i: Integer;
  name: array[0..255] of Char;
  sfx: sfx_p;
begin
  i := 1;
  while (i < Cmd_Argc()) do
  begin
    if not (strchr(Cmd_Argv(i), Byte('.')) <> nil) then
    begin
      strcpy(name, Cmd_Argv(i));
      strcat(name, '.wav');
    end
    else
      strcpy(name, Cmd_Argv(i));
    sfx := S_RegisterSound(name);
    S_StartSound(nil, cl.playernum + 1, 0, sfx, 1.0, 1.0, 0);
    Inc(i);
  end;
end;

procedure S_SoundList;
var
  i: Integer;
  sc: sfxcache_p;
  size: Integer;
  total: Integer;
begin
  total := 0;
  for i := 0 to num_sfx - 1 do
  begin
    if (known_sfx[i].registration_sequence = 0) then
      continue;
    sc := known_sfx[i].cache;
    if (sc <> nil) then
    begin
      size := sc^.length * sc^.width * (sc^.stereo + 1);
      total := total + size;
      if (sc^.loopstart >= 0) then
        Com_Printf('L', [])
      else
        Com_Printf(' ', []);
      Com_Printf('(%2db) %6i : %s'#10, [sc^.width * 8, size, known_sfx[i].name]);
    end
    else
    begin
      if (known_sfx[i].name[0] = '*') then
        Com_Printf('  placeholder : %s'#10, [known_sfx[i].name])
      else
        Com_Printf('  not loaded  : %s'#10, [known_sfx[i].name]);
    end;
  end;
  Com_Printf('Total resident: %d'#10, [total]);
end;

end.

⌨️ 快捷键说明

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