This file is indexed.

/usr/src/castle-game-engine-5.2.0/audio/castlevorbisdecoder.pas is in castle-game-engine-src 5.2.0-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
{ OggVorbis decoder. }
unit CastleVorbisDecoder;

interface

uses SysUtils, Classes, CastleOpenAL;

type
  EVorbisLoadError = class(Exception);
  EVorbisFileError = class(EVorbisLoadError);

{ OggVorbis decoder using vorbisfile library and working on
  ObjectPascal TStream objects.

  This checks VorbisFileInited at the beginning, so you don't have to
  worry about it.

  Note: this only uses some constants from OpenAL unit. It doesn't
  actually require OpenAL library to be available and initialized.

  @raises EReadError If Stream cannot be read (e.g. ended prematurely.)
  @raises EVorbisLoadError If decoding OggVorbis stream failed. }
function VorbisDecode(Stream: TStream; out DataFormat: TALuint;
  out Frequency: LongWord): TMemoryStream;

implementation

uses CastleUtils, CastleVorbisFile, CastleVorbisCodec, CTypes;

{$I vorbisfile_conf.inc}

{ VorbisDecoder_ callbacks code based on Noeska code from
  [http://www.noeska.com/doal/tutorials.aspx].
  I (Michalis) heavily modified it (e.g. to allow exceptions raising in case of
  stream errors (instead of silencing these exceptions), to check (ReadCount mod
  Size) in read_func and whence in seek_func, close does nothing),
  but still the idea remains.

  I made my own CastleVorbisFile header, and later realized that actually
  someone already did something similar...
  But from the first glance, JEDI CastleVorbisFile
  header shows some problems --- as usual, the JEDI guys don't have a clue
  about FPC or any OS that isn't Windows. Besides, my CastleVorbisFile will not
  cause exception at initialization if vorbisfile will not be installled ---
  this is crucial for me. So I will continue using my own CastleVorbisFile unit. }

function VorbisDecoder_read_func(ptr: Pointer;
  Size: TSizeT; nmemb: TSizeT; DataSource: Pointer): TSizeT; libvorbisfile_decl;
{ Returns amount of items completely read successfully, returns indeterminate
  value on error. The value of a partially read item cannot be determined. Does
  not lead to valid feof or ferror responses, because they are not possible to
  supply to VorbisFile }
var
  ReadCount: Int64;
begin
  if (size = 0) or (nmemb = 0) then
  begin
    Result := 0;
    Exit;
  end;

  ReadCount := TStream(DataSource).Read(ptr^, Size * nmemb);
  Assert(ReadCount mod Size = 0);
  Result := ReadCount div Size;
end;

function VorbisDecoder_seek_func(DataSource: Pointer;
  offset: Int64; whence: CInt): CInt; libvorbisfile_decl;
const
  SEEK_SET = 0;
  SEEK_CUR = 1;
  SEEK_END = 2;
begin
  try
    case whence of
      SEEK_CUR: TStream(DataSource).Seek(offset, soFromCurrent);
      SEEK_END: TStream(DataSource).Seek(offset, soFromEnd);
      SEEK_SET: TStream(DataSource).Seek(offset, soFromBeginning);
      else raise EInternalError.CreateFmt('Invalid VorbisDecoder_seek_func ' +
        'whence param: %d', [whence]);
    end;
    Result := 0;
  except
    { If the Stream is unseekable, vorbisfile allows us to return here -1. }
    Result := -1;
  end;
end;

function VorbisDecoder_close_func(DataSource: Pointer): CInt;
  libvorbisfile_decl;
begin
  Result := 0;
end;

function VorbisDecoder_tell_func(DataSource: Pointer): CLong;
  libvorbisfile_decl;
begin
  Result := TStream(DataSource).Position;
end;

{ Simple encoding of OggVorbis is implemented based on
  [http://www.gamedev.net/reference/articles/article2031.asp].
  I reworked it a lot (I have to use callbacks to handle Pascal streams,
  I check for errors). See [http://xiph.org/vorbis/doc/vorbisfile/index.html]
  for vorbisfile overview. }

function VorbisDecode(Stream: TStream; out DataFormat: TALuint;
  out Frequency: LongWord): TMemoryStream;

  procedure CheckVorbisFile(Err: CInt; const Event: string);
  var
    ErrDescription: string;
  begin
    { Errors list and ErrDescription values based on
      [http://xiph.org/vorbis/doc/vorbisfile/return.html] }
    case Err of
      OV_FALSE: ErrDescription := 'No data available';
      OV_HOLE: ErrDescription := 'Vorbisfile encountered missing or corrupt data in the bitstream'; {. Recovery is normally automatic and this return code is for informational purposes only. }
      OV_EREAD: ErrDescription := 'Read error while fetching compressed data for decode';
      OV_EFAULT: ErrDescription := 'Internal inconsistency in decode state'; {. Continuing is likely not possible. }
      OV_EIMPL: ErrDescription := 'Feature not implemented';
      OV_EINVAL: ErrDescription := 'Either an invalid argument, or incompletely initialized argument passed to libvorbisfile call';
      OV_ENOTVORBIS: ErrDescription := 'The given file/data was not recognized as Ogg Vorbis data';
      OV_EBADHEADER: ErrDescription := 'The file/data is apparently an Ogg Vorbis stream, but contains a corrupted or undecipherable header';
      OV_EVERSION: ErrDescription := 'The bitstream format revision of the given stream is not supported';
      OV_EBADLINK: ErrDescription := 'The given link exists in the Vorbis data stream, but is not decipherable due to garbacge or corruption';
      OV_ENOSEEK: ErrDescription := 'The given stream is not seekable';
      else ErrDescription := '(unknown vorbisfile error code)';
    end;

    if Err <> 0 then
      raise EVorbisFileError.CreateFmt('VorbisFile error %d at "%s": %s',
        [Err, Event, ErrDescription]);
  end;

const
  { Noone uses ogg vorbis with small files, so it's sensible to make
    this buffer at least 1 MB. Above this, increasing BufSize doesn't
    seem to make loading OggVorbis faster. }
  BufSize = 1000 * 1000;

var
  OggFile: TOggVorbis_File;
  OggInfo: Pvorbis_info;
  Callbacks: Tov_callbacks;
  ReadCount: CLong;
  Buffer: Pointer;
  BitStream: CInt;
begin
  if not VorbisFileInited then
    raise EVorbisLoadError.Create('vorbisfile library is not available, ' +
      'cannot decode OggVorbis file');

  Result := TMemoryStream.Create;
  try
    Callbacks.read_func := @VorbisDecoder_read_func;
    Callbacks.seek_func := @VorbisDecoder_seek_func;
    Callbacks.close_func := @VorbisDecoder_close_func;
    Callbacks.tell_func := @VorbisDecoder_tell_func;
    CheckVorbisFile(ov_open_callbacks(Stream, @OggFile, nil, 0, Callbacks),
      'ov_open_callbacks');

    OggInfo := ov_info(@OggFile, -1);

    if OggInfo^.channels = 1 then
      DataFormat := AL_FORMAT_MONO16 else
      DataFormat := AL_FORMAT_STEREO16;

    Frequency := OggInfo^.rate;

    Buffer := GetMem(BufSize);
    try

      repeat
        ReadCount := ov_read(@OggFile, Buffer^, BufSize,
          { OpenAL always wants little endian ? } 0,
          { Always give us 16 bits } 2, 1, @BitStream);

        if ReadCount < 0 then
          CheckVorbisFile(ReadCount, 'ov_read');

        Result.WriteBuffer(Buffer^, ReadCount);
      until ReadCount <= 0;

    finally FreeMemNiling(Buffer) end;

    ov_clear(@OggFile);
  except
    FreeAndNil(Result);
    raise;
  end;
end;

end.