![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | 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. |