fpwavwriter.pas 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. {*****************************************************************************}
  2. {
  3. This file is part of the Free Pascal's "Free Components Library".
  4. Copyright (c) 2014 by Mazen NEIFER of the Free Pascal development team
  5. and was adapted from wavopenal.pas copyright (c) 2010 Dmitry Boyarintsev.
  6. RIFF/WAVE sound file writer implementation.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. }
  13. unit fpwavwriter;
  14. {$mode objfpc}{$H+}
  15. interface
  16. uses
  17. fpWavFormat,
  18. Classes;
  19. type
  20. { TWaveReader }
  21. { TWavWriter }
  22. TWavWriter = class(TObject)
  23. private
  24. fStream: TStream;
  25. FFreeStreamOnClose: Boolean;
  26. public
  27. fmt: TWaveFormat;
  28. destructor Destroy; override;
  29. function CloseAudioFile: Boolean;
  30. function FlushHeader: Boolean;
  31. function StoreToFile(const FileName: string): Boolean;
  32. function StoreToStream(AStream: TStream): Boolean;
  33. function WriteBuf(var Buffer; BufferSize: Integer): Integer;
  34. end;
  35. implementation
  36. uses
  37. SysUtils;
  38. procedure NtoLE(var fmt: TWaveFormat); overload;
  39. begin
  40. with fmt, ChunkHeader do begin
  41. Size := NtoLE(Size);
  42. Format := NtoLE(Format);
  43. Channels := NtoLE(Channels);
  44. SampleRate := NtoLE(SampleRate);
  45. ByteRate := NtoLE(ByteRate);
  46. BlockAlign := NtoLE(BlockAlign);
  47. BitsPerSample := NtoLE(BitsPerSample);
  48. end;
  49. end;
  50. { TWaveWriter }
  51. destructor TWavWriter.Destroy;
  52. begin
  53. CloseAudioFile;
  54. inherited Destroy;
  55. end;
  56. function TWavWriter.CloseAudioFile: Boolean;
  57. begin
  58. Result := True;
  59. if not Assigned(fStream) then begin
  60. Exit(True);
  61. end;
  62. FlushHeader;
  63. if FFreeStreamOnClose then begin
  64. fStream.Free;
  65. end;
  66. end;
  67. function TWavWriter.FlushHeader: Boolean;
  68. var
  69. riff: TRiffHeader;
  70. fmtLE: TWaveFormat;
  71. DataChunk: TChunkHeader;
  72. Pos: Int64;
  73. begin
  74. Pos := fStream.Position;
  75. with riff, ChunkHeader do begin
  76. ID := AUDIO_CHUNK_ID_RIFF;
  77. Size := NtoLE(Pos - SizeOf(ChunkHeader));
  78. Format := AUDIO_CHUNK_ID_WAVE;
  79. end;
  80. fmtLE := fmt;
  81. NtoLE(fmtLE);
  82. with fStream do begin
  83. Position := 0;
  84. Result := Write(riff, SizeOf(riff)) = SizeOf(riff);
  85. Result := Write(fmtLE, sizeof(fmtLE)) = SizeOf(fmtLE);
  86. end;
  87. with DataChunk do begin
  88. Id := AUDIO_CHUNK_ID_data;
  89. Size := Pos - SizeOf(DataChunk) - fStream.Position;
  90. end;
  91. with fStream do begin
  92. Result := Write(DataChunk, SizeOf(DataChunk)) = SizeOf(DataChunk);
  93. end;
  94. end;
  95. function TWavWriter.StoreToFile(const FileName: string):Boolean;
  96. begin
  97. CloseAudioFile;
  98. fStream := TFileStream.Create(FileName, fmCreate + fmOpenWrite);
  99. if Assigned(fStream) then begin
  100. Result := StoreToStream(fStream);
  101. FFreeStreamOnClose := True;
  102. end else begin
  103. Result := False;
  104. end;
  105. end;
  106. function TWavWriter.StoreToStream(AStream:TStream):Boolean;
  107. begin
  108. fStream := AStream;
  109. FFreeStreamOnClose := False;
  110. with fmt, ChunkHeader do begin
  111. ID := AUDIO_CHUNK_ID_fmt;
  112. Size := SizeOf(fmt) - SizeOf(ChunkHeader);
  113. Format := AUDIO_FORMAT_PCM;
  114. end;
  115. Result := FlushHeader;
  116. end;
  117. function TWavWriter.WriteBuf(var Buffer; BufferSize: Integer): Integer;
  118. var
  119. sz: Integer;
  120. begin
  121. Result := 0;
  122. with fStream do begin
  123. sz := Write(Buffer, BufferSize);
  124. if sz < 0 then Exit;
  125. Inc(Result, sz);
  126. end;
  127. end;
  128. end.