|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#106
|
||||
|
||||
Цитата:
Цитата:
|
#107
|
|||
|
|||
Цитата:
|
#108
|
||||
|
||||
Цитата:
Но я советую передавать прочитанные сэмплы через динамический массив (в структуре TWaveResult), а не через Memo. |
#109
|
|||
|
|||
Цитата:
|
#110
|
||||
|
||||
Цитата:
Код:
procedure TForm1.ButtonClick(Sender: TObject); var WaveResult: TWaveResult; begin if OpenDialog.Execute then begin WaveResult := ReadWave(OpenDialog.FileName); end; if SaveDialog.Execute then begin WriteWav(SaveDialog.FileName, WaveResult); end; end; |
#111
|
|||
|
|||
Цитата:
|
#112
|
||||
|
||||
Цитата:
А пока не изучены базовые понятия, писать прикладные программы рановато. И у меня создаётся впечатление, что вы хотите, чтобы я написал всю программу за вас? Или я ошибаюсь? |
#113
|
|||
|
|||
Цитата:
|
#114
|
||||
|
||||
Цитата:
Код:
type EWavError = class(Exception); TWaveFormat = packed record wFormatTag: Word; nChannels: Word; nSamplesPerSec: DWORD; nAvgBytesPerSec: DWORD; nBlockAlign: Word; wBitsPerSample: Word; end; TWavInfo = record WaveFormat: TWaveFormat; Samples: array of array of Word; end; const WAVE_FORMAT_PCM = $0001; procedure RaiseWavError(const Msg: string); begin raise EWavError.Create(Msg); end; procedure ReadWavInfo(const FileName: string; var WavInfo: TWavInfo); type TChunkName = packed array[0..3] of AnsiChar; TRiffChunk = packed record RiffSign: TChunkName; RiffSize: Longword; WaveSign: TChunkName; end; TChunk = packed record Name: TChunkName; Size: Longword; end; var fs: TFileStream; RiffChunk: TRiffChunk; Chunk: TChunk; FmtPos, DataPos, NewPos: Int64; DataSize, NumSamples, BytsPerSample, I, J: Longword; procedure DecRiffSize(Size: Longword); begin if RiffChunk.RiffSize < Size then RaiseWavError('Wav-файл повреждён'); Dec(RiffChunk.RiffSize, Size); end; begin Finalize(WavInfo); FillChar(WavInfo, SizeOf(WavInfo), 0); fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); try fs.ReadBuffer(RiffChunk, SizeOf(RiffChunk)); if (RiffChunk.RiffSign <> 'RIFF') or (RiffChunk.WaveSign <> 'WAVE') then RaiseWavError('Это не wav-файл'); DecRiffSize(SizeOf(RiffChunk.WaveSign)); FmtPos := 0; DataPos := 0; while RiffChunk.RiffSize > 0 do begin fs.ReadBuffer(Chunk, SizeOf(Chunk)); DecRiffSize(SizeOf(Chunk)); DecRiffSize(Chunk.Size); if Chunk.Name = 'fmt ' then begin if FmtPos <> 0 then RaiseWavError('Встретилось несколько секций "fmt"'); if Chunk.Size < SizeOf(WavInfo.WaveFormat) then RaiseWavError('Неверный размер секции "fmt"'); FmtPos := fs.Position; end else if Chunk.Name = 'data' then begin if DataPos <> 0 then RaiseWavError('Встретилось несколько секций "data"'); DataPos := fs.Position; DataSize := Chunk.Size; end; NewPos := fs.Position + Chunk.Size; fs.Position := NewPos; if fs.Position <> NewPos then RaiseWavError('Wav-файл повреждён'); end; if FmtPos = 0 then RaiseWavError('Отсутствует секция "fmt"'); if DataPos = 0 then RaiseWavError('Отсутствует секция "data"'); fs.Position := FmtPos; fs.ReadBuffer(WavInfo.WaveFormat, SizeOf(WavInfo.WaveFormat)); if WavInfo.WaveFormat.wFormatTag = WAVE_FORMAT_PCM then begin if WavInfo.WaveFormat.nChannels = 0 then RaiseWavError('Отсутствуют каналы'); BytsPerSample := WavInfo.WaveFormat.wBitsPerSample div 8; if BytsPerSample = 0 then RaiseWavError('Неверная разрядность сэмплов'); NumSamples := DataSize div (BytsPerSample * WavInfo.WaveFormat.nChannels); SetLength(WavInfo.Samples, NumSamples, WavInfo.WaveFormat.nChannels); fs.Position := DataPos; for I := 1 to NumSamples do begin for J := 1 to WavInfo.WaveFormat.nChannels do begin fs.ReadBuffer(WavInfo.Samples[I - 1, J - 1], BytsPerSample); end; end; end; finally fs.Free; end; end; procedure WriteWav(const FileName: string; const WavInfo: TWavInfo); type TChunkID = packed array[0..3] of Char; THeader = packed record ChunkID: TChunkID; ChunkSize: Longword; Format: TChunkID; Subchunk1ID: TChunkID; Subchunk1Size: Longword; AudioFormat: Word; NumChannels: Word; SampleRate: Longword; ByteRate: Longword; BlockAlign: Word; BitsPerSample: Word; Subchunk2ID: TChunkID; Subchunk2Size: Longword; end; var Header: THeader; NumSamples, BytsPerSample, Sample, I, J: Longword; fs: TFileStream; begin NumSamples := Length(WavInfo.Samples); BytsPerSample := WavInfo.WaveFormat.wBitsPerSample div 8; Header.ChunkID := 'RIFF'; Header.Format := 'WAVE'; Header.Subchunk1ID := 'fmt '; Header.Subchunk1Size := 16; Header.AudioFormat := WAVE_FORMAT_PCM; // Только PCM Header.NumChannels := WavInfo.WaveFormat.nChannels; Header.SampleRate := WavInfo.WaveFormat.nSamplesPerSec; Header.BitsPerSample := BytsPerSample * 8; Header.BlockAlign := Header.NumChannels * BytsPerSample; Header.ByteRate := Header.SampleRate * Header.BlockAlign; Header.Subchunk2ID := 'data'; Header.Subchunk2Size := NumSamples * Header.BlockAlign; Header.ChunkSize := Header.Subchunk2Size + SizeOf(Header) - 8; fs := TFileStream.Create(FileName, fmCreate); try fs.WriteBuffer(Header, SizeOf(Header)); for I := 1 to NumSamples do begin for J := 1 to Header.NumChannels do begin fs.WriteBuffer(WavInfo.Samples[I - 1, J - 1], BytsPerSample); end; end; finally fs.Free; end; end; procedure TForm1.ButtonClick(Sender: TObject); var WavInfo: TWavInfo; begin if OpenDialog.Execute then begin ReadWavInfo(OpenDialog.FileName, WavInfo); Memo.ScrollBars := ssBoth; Memo.WordWrap := False; Memo.Clear; Memo.Lines.Add('Файл: ' + OpenDialog.FileName); Memo.Lines.Add('Формат: $' + IntToHex(WavInfo.WaveFormat.wFormatTag, 4)); Memo.Lines.Add('Каналов: ' + IntToStr(WavInfo.WaveFormat.nChannels)); Memo.Lines.Add('Сэмплов: ' + IntToStr(Length(WavInfo.Samples))); Memo.Lines.Add('Частота дискретизации: ' + IntToStr(WavInfo.WaveFormat.nSamplesPerSec) + ' сэмплов в секунду'); Memo.Lines.Add('Разрядность сэмплов: ' + IntToStr(WavInfo.WaveFormat.wBitsPerSample) + ' бит'); if WavInfo.WaveFormat.wFormatTag = WAVE_FORMAT_PCM then begin if SaveDialog.Execute then begin WriteWav(SaveDialog.FileName, WavInfo); end; end; end; end; |
Этот пользователь сказал Спасибо poli-smen за это полезное сообщение: | ||
Dmitry_DM (17.08.2012)
|
#115
|
|||
|
|||
Цитата:
|
#116
|
|||
|
|||
Эта версия программы как бы "закрытая". В следствии программы изменить что то будет сложно в данных. Я хочу большую нужную ее часть использовать для дополнения моей версии. Как думаете, получиться?
|
#117
|
||||
|
||||
Цитата:
|
#118
|
|||
|
|||
Цитата:
|
#119
|
|||
|
|||
У меня есть успешный прогресс. Я грамотно склеил вашу программу с моей и неплохо получилось. Ошибки не выдает. Пока не большие проблемы с записью инфы в мемо1 и трудности при оброботки команды запись (кнопка не нажимается). Это я думаю поправимо. Завтра попробую доделать и выложить исходный код. Может будут проблемы. Надеюсь, вы мне поможете?
|
#120
|
|||
|
|||
Пока что у меня проблемы с записью данных в memo1. Можете посмотреть на код и сказать что сделать, что бы данные шли в своем порядке. А то ни как не могу сделать красиво и ровно. должно быть так:
Код:
RIFF chunkSize 2194 WAVE fmt subchunk1Size 16 audioFormat 1 numChannels 1 sampleRate 22050 byteRate 44100 blockAlign 2 bitsPerSample 16 data subchunk2Size 2158 Код:
RIFF WAVE fmt 16 data 2158 audioFormat 0001 numChannels 1 sampleRate 22050 byteRate 44100 blockAlign 2 bitsPerSample 16 Код: Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Menus, sSkinManager, ImgList, Inifiles, ComCtrls, sTabControl, acHeaderControl, sGauge, sPageControl, sMemo, sButton; Const noError = 0; ReadError = 1; HeaderError = 2; DataError = 3; FileCorrupt = 4; IncorectFileFormat = 5; WAVE_FORMAT_PCM = 1; type TForm1 = class(TForm) OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; MainMenu1: TMainMenu; N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; N4: TMenuItem; N5: TMenuItem; N6: TMenuItem; N7: TMenuItem; N8: TMenuItem; N9: TMenuItem; N10: TMenuItem; N11: TMenuItem; N12: TMenuItem; sSkinManager1: TsSkinManager; ImageList1: TImageList; SaveDialog2: TSaveDialog; TabSheet1: TsTabSheet; TabSheet2: TsTabSheet; Memo1: TsMemo; Memo2: TsMemo; Button1: TsButton; Button2: TsButton; Button3: TsButton; Button4: TsButton; Button5: TsButton; Button6: TsButton; OpenDialog2: TOpenDialog; PageControl1: TsPageControl; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Button6Click(Sender: TObject); procedure N2Click(Sender: TObject); procedure N3Click(Sender: TObject); procedure N5Click(Sender: TObject); procedure N6Click(Sender: TObject); procedure FormShow(Sender: TObject); procedure N8Click(Sender: TObject); procedure N9Click(Sender: TObject); procedure N10Click(Sender: TObject); procedure N11Click(Sender: TObject); procedure N12Click(Sender: TObject); { Private declarations } public { Public declarations } end; type EWavError = class(Exception); TWaveFormat = packed record wFormatTag: Word; nChannels: Word; nSamplesPerSec: DWORD; nAvgBytesPerSec: DWORD; nBlockAlign: Word; wBitsPerSample: Word; end; TWavInfo = record WaveFormat: TWaveFormat; Samples: array of array of Word; end; var Form1: TForm1; TxtFile : TextFile; i : integer; sample: Int64; SampleSize, chanel: Longword; NumSamples: Longword; s1: String; s2: integer; Ini:Tinifile; language:string; implementation {$R *.dfm} {$R WindowsXP.res} uses math, Unit2; procedure RaiseWavError(const Msg: string); begin raise EWavError.Create(Msg); end; procedure ReadWavInfo(const FileName: string; var WavInfo: TWavInfo); type TChunkName = packed array[0..3] of AnsiChar; TRiffChunk = packed record RiffSign: TChunkName; RiffSize: Longword; WaveSign: TChunkName; end; TChunk = packed record Name: TChunkName; Size: Longword; end; var fs: TFileStream; RiffChunk: TRiffChunk; Chunk: TChunk; FmtPos, DataPos, NewPos: Int64; DataSize, NumSamples, BytsPerSample, I, J: Longword; procedure DecRiffSize(Size: Longword); begin if RiffChunk.RiffSize < Size then RaiseWavError('Wav-файл повреждён'); Dec(RiffChunk.RiffSize, Size); end; begin Finalize(WavInfo); FillChar(WavInfo, SizeOf(WavInfo), 0); fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); try fs.ReadBuffer(RiffChunk, SizeOf(RiffChunk)); if (RiffChunk.RiffSign <> 'RIFF') or (RiffChunk.WaveSign <> 'WAVE') then RaiseWavError('Это не wav-файл'); DecRiffSize(SizeOf(RiffChunk.WaveSign)); Form1.memo1.Lines.Add(RiffChunk.RiffSign); Form1.memo1.Lines.Add(RiffChunk.WaveSign); FmtPos := 0; DataPos := 0; while RiffChunk.RiffSize > 0 do begin fs.ReadBuffer(Chunk, SizeOf(Chunk)); DecRiffSize(SizeOf(Chunk)); DecRiffSize(Chunk.Size); if Chunk.Name = 'fmt ' then begin if FmtPos <> 0 then RaiseWavError('Встретилось несколько секций "fmt"'); if Chunk.Size < SizeOf(WavInfo.WaveFormat) then RaiseWavError('Неверный размер секции "fmt"'); FmtPos := fs.Position; end else if Chunk.Name = 'data' then begin if DataPos <> 0 then RaiseWavError('Встретилось несколько секций "data"'); DataPos := fs.Position; DataSize := Chunk.Size; end; NewPos := fs.Position + Chunk.Size; fs.Position := NewPos; if fs.Position <> NewPos then RaiseWavError('Wav-файл повреждён'); end; if FmtPos = 0 then RaiseWavError('Отсутствует секция "fmt"'); if DataPos = 0 then RaiseWavError('Отсутствует секция "data"'); fs.Position := FmtPos; fs.ReadBuffer(WavInfo.WaveFormat, SizeOf(WavInfo.WaveFormat)); if WavInfo.WaveFormat.wFormatTag = WAVE_FORMAT_PCM then begin if WavInfo.WaveFormat.nChannels = 0 then RaiseWavError('Отсутствуют каналы'); BytsPerSample := WavInfo.WaveFormat.wBitsPerSample div 8; if BytsPerSample = 0 then RaiseWavError('Неверная разрядность сэмплов'); NumSamples := DataSize div (BytsPerSample * WavInfo.WaveFormat.nChannels); SetLength(WavInfo.Samples, NumSamples, WavInfo.WaveFormat.nChannels); fs.Position := DataPos; for I := 1 to NumSamples do begin for J := 1 to WavInfo.WaveFormat.nChannels do begin fs.ReadBuffer(WavInfo.Samples[I - 1, J - 1], BytsPerSample); end; end; end; finally fs.Free; end; end; Последний раз редактировалось Dmitry_DM, 19.08.2012 в 17:02. |