Ни для кого не секрет, что библиотека bass.dll может не только воспроизводить, но и записывать звук.
Единственная проблема, запись возможна только в поток. Например, TMemoryStream, как в демонстрационном примере RecordTest из комплекта поставки.
Для того чтобы сохранить записанные аудиоданные в файл необходимо перенести данные из потока на жёсткий диск компьютера или карту памяти.
Эта задача сама по себе не представляет особой сложности. Дело в том, что предлагаемый в примере TMemoryStream имеет метод SaveToFile, который сохраняет в файл его содержимое.
Таким образом, чтобы реализовать возможность сохранения записанных данных в файл, по сути, достаточно одной строки кода.
1 |
WaveStream.SaveToFile('FileName.wav'); |
Однако, это не единственный способ. Существует ещё одна недокументированная возможность сохранить в файл записанную звуковую информацию.
Речь идёт о прямой записи в файл с использованием TFileStream или файлового потока.
При таком подходе получаемые звуковые данные сразу же записываются в файл без промежуточного накопления в памяти, как в случае TMemoryStream.
Рассмотрим программную реализацию этого подхода.
В начале, как и при записи с использованием TMemoryStream, опишем запись для заголовка WAV данных.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
type WAVHDR = packed record riff: array [0 .. 3] of AnsiChar; len: DWord; cWavFmt: array [0 .. 7] of AnsiChar; dwHdrLen: DWord; wFormat: Word; wNumChannels: Word; dwSampleRate: DWord; dwBytesPerSec: DWord; wBlockAlign: Word; wBitsPerSample: Word; cData: array [0 .. 3] of AnsiChar; dwDataLen: DWord; end; |
Более подробную информацию о его структуре и назначении его элементов можно получить в описании формата WAV. При записи в файл первостепенную роль будет играть его последний элемент dwDataLen, который хранит продолжительность записи.
После этого задекларируем две переменные. Первая будет хранить информацию заголовка WAV, а вторая поток записываемых звуковых данных.
1 2 3 4 |
var … rchan: HRECORD; WaveHdr: WAVHDR; |
И выполним при запуске программы (желательно) инициализацию библиотеки bass.dll для записи.
1 2 |
if Bass_RecordInit(-1) = false then ShowMessage('Не могу инициализировать запись!'); |
Далее объявим в классе формы открытое поле типа TFileStream.
1 |
fs: TfileStream; |
Напишем функцию обратного вызова таким образом, чтобы записываемые данные сохранялись именно в это поле.
1 2 3 4 5 |
function RecordingCallback(Handle: HRECORD; buffer: Pointer; length: DWord; user: Pointer): boolean; stdcall; begin Main.fs.Write(buffer^, length); Result := True; end; |
Для того чтобы начать запись нужно инициализировать файловый поток с правами на запись.
1 |
fs := TfileStream.Create('FileName.wav', fmCreate or fmOpenWrite); |
Затем сформировать и записать в него заголовок
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
fs.Position := 0; with WaveHdr do begin riff := 'RIFF'; len := 36; cWavFmt := 'WAVEfmt '; dwHdrLen := 16; wFormat := 1; wNumChannels := 2; dwSampleRate := 44100; wBlockAlign := 4; dwBytesPerSec := 176400; wBitsPerSample := 16; cData := 'data'; dwDataLen := 0; end; fs.Write(WaveHdr, SizeOf(WAVHDR)); |
Так как продолжительность записи заранее неизвестна, присвоим элементу dwDataLen значение «0».
После этого можно запустить процесс записи.
1 |
rchan := BASS_RecordStart(44100, 2, 0, @RecordingCallback, nil); |
По завершении записи вычисляем её продолжительность и записываем в элемент dwDataLen заголовка (иначе файл не будет воспроизводиться) и освобождаем поток.
1 2 3 4 5 6 7 8 9 10 11 12 |
var i: int64; begin BASS_ChannelStop(rchan); fs.Position := 4; i := fs.Size - 8; fs.Write(i, 4); i := i - $24; fs.Position := 40; fs.Write(i, 4); fs.Free; end; |
Если всё сделано правильно, по указанному адресу можно будет найти файл .wav со звукозаписью и прослушать её.
Добавить комментарий