Корочее так правильно! Но теперь запись не происходит, пишет: 'wave' is not a valid integer value.
Это вам скорее всего пишет, что во второй строке Memo2 слово 'wave' и естественно оно не может быть преобразовано в число.
Строка вида '1234' может быть преобразована в число 1234, но строка вида 'wave' естественно ни в какое число не может быть преобразована.
Цитата:
Сообщение от Dmitry_DM
Как теперь при записи сделать снова string?
Чтобы число преобразовать в строку есть функция IntToStr().
Это вам скорее всего пишет, что во второй строке Memo2 слово 'wave' и естественно оно не может быть преобразовано в число.
Строка вида '1234' может быть преобразована в число 1234, но строка вида 'wave' естественно ни в какое число не может быть преобразована.
Чтобы число преобразовать в строку есть функция IntToStr().
Так я это знаю, поэтому и не трогал RIFF, WAVE, fmt , data. Вот так у меня:
procedure TForm1.Button4Click(Sender: TObject);
begin
if SaveDialog2.Execute then
begin
WriteWav(SaveDialog2.FileName);
end;
Что теперь делать???
На вид всё нормально. Компилятор ругается?
Вы же конечно знаете, что нумерация строк в Memo начинается с нуля? Нумерация с нуля в компьютерной технике вообще нормальное явление.
На вид всё нормально. Компилятор ругается?
Вы же конечно знаете, что нумерация строк в Memo начинается с нуля? Нумерация с нуля в компьютерной технике вообще нормальное явление.
Вот я тупой, голова с дырой! Спасибо, товарищ!!! Все дело в 1 строке, которая "0"
Теперь во всем деле есть только 3 проблемы. И все! На этом проект пока приостанавливается. Но все же есть 3 проблемы: первая - это почему при считывании самих сэмплов идет, к примеру так: FFFA 000A FFEE, а должно быть FAFF 0A00 EEFF. В проф. HEX эдиторе так. Можно это как то поменять местами 2 символа при выводе? Вот код:
Код:
if Header.wFormatTag<>1 then
begin
Form1.Memo1.Lines.Add('ОШИБКА! Я умею читать wav-файлы только в формате PCM, а этот файл в формате 0x'+IntToHex(Header.wFormatTag, 4));
end;
SampleSize:=(Header.wBitsPerSample+7) div 8;
if SampleSize>SizeOf(sample) then
begin
Form1.Memo1.Lines.Add('ОШИБКА! Слишком большой размер сэмпла ('+IntToStr(SampleSize)+' байт)');
Exit;
end;
if Header.wChannels=0 then
begin
Form1.Memo1.Lines.Add('ОШИБКА! Нет каналов');
Exit;
end;
Form1.Memo1.WordWrap:=False;
Form1.Memo1.ScrollBars:=ssBoth;
sample:=0;
i:=0;
while wChankSize>=(SampleSize*Header.wChannels) do
begin
if Header.wBlockAlign>0 then
begin
n:=f.Position mod Header.wBlockAlign;
if n>0 then
begin
n:=Header.wBlockAlign-n;
f.Seek(n, soFromCurrent);
Dec(wChankSize, n);
if wChankSize<(SampleSize*Header.wChannels) then Break;
end;
end;
Inc(i);
s1:='';
s:=''+IntToStr(i);
for chanel := 1 to Header.wChannels do
begin
f.ReadBuffer(sample, SampleSize);
Dec(wChankSize, SampleSize);
s:=s+' Chanel'+IntToStr(chanel)+' '+IntToHex(sample, SampleSize*2);
s1:=IntToHex(sample, SampleSize*2);
end;
Form1.Memo1.Lines.Add(s1);
end;
exit;
f.Free;
Except
Result.ERROR := ReadError;
end;
end;
Вторая проблема: Я еле смог сделать вывод сэмплов в "чистом виде", то есть без семпл:такой-то, канал 1: "значение". Сделал только значение. Но исходит проблема: в 2-х канальном wav не выводиться так FFFAFFFA, а только так: FFFA. Как сделать, чтобы рядом и второй канал приписывался? А 3 проблему расскажу потом.
Теперь во всем деле есть только 3 проблемы. И все! На этом проект пока приостанавливается. Но все же есть 3 проблемы: первая - это почему при считывании самих сэмплов идет, к примеру так: FFFA 000A FFEE, а должно быть FAFF 0A00 EEFF. В проф. HEX эдиторе так. Можно это как то поменять местами 2 символа при выводе?
Менять ничего не нужно. Числа хранятся в обратном порядке: сначала младший байт, в конце старший байт. HEX эдитор показывает числа, в том виде, как они и хранятся, т.е. в перевёрнутом виде. А при считывании числа отображаются нормально. Например число $01234567 будет храниться так: 67 45 23 01
Цитата:
Сообщение от Dmitry_DM
Вторая проблема: Я еле смог сделать вывод сэмплов в "чистом виде", то есть без семпл:такой-то, канал 1: "значение". Сделал только значение. Но исходит проблема: в 2-х канальном wav не выводиться так FFFAFFFA, а только так: FFFA. Как сделать, чтобы рядом и второй канал приписывался? А 3 проблему расскажу потом.
Ну в старом виде, как вы мне давали, были слова и цифры, препятствующие будущей записи, типа номер семпла, канал, значение. Было так:
1 Канал1: 0000 Канал2: 0000
2 Канал1: 0002 Канал2: 0002
И т.д...
Но потом я сделал так, чтобы выводилось только значение. 0002, например. В одноканальном проблем нет, так как там 0002 и все. Но так же выводит и для 2-х канального. А должно быть так 00020002. То есть 2 канала рядом. как так вывести? В правильном итоге, как на картинке, в не правильном, значение в одном канале.
Последний раз редактировалось Dmitry_DM, 14.08.2012 в 16:25.
Ну в старом виде, как вы мне давали, были слова и цифры, препятствующие будущей записи, типа номер семпла, канал, значение. Было так:
1 Канал1: 0000 Канал2: 0000
2 Канал1: 0002 Канал2: 0002
И т.д...
Но потом я сделал так, чтобы выводилось только значение. 0002, например. В одноканальном проблем нет, так как там 0002 и все. Но так же выводит и для 2-х канального. А должно быть так 00020002. То есть 2 канала рядом. как так вывести? В правильном итоге, как на картинке, в не правильном, значение в одном канале.
Здесь должно быть так:
Код:
Inc(i);
s1:='';
s:=''+IntToStr(i);
for chanel := 1 to Header.wChannels do
begin
f.ReadBuffer(sample, SampleSize);
Dec(wChankSize, SampleSize);
s:=s+' Chanel'+IntToStr(chanel)+' '+IntToHex(sample, SampleSize*2);
s1:=s1+IntToHex(sample, SampleSize*2);// <=======
end;
Form1.Memo1.Lines.Add(s1);
А для каких целей в этом коде используется переменная s ?
Inc(i);
s1:='';
s:=''+IntToStr(i);
for chanel := 1 to Header.wChannels do
begin
f.ReadBuffer(sample, SampleSize);
Dec(wChankSize, SampleSize);
s:=s+' Chanel'+IntToStr(chanel)+' '+IntToHex(sample, SampleSize*2);
s1:=s1+IntToHex(sample, SampleSize*2);// <=======
end;
Form1.Memo1.Lines.Add(s1);
А для каких целей в этом коде используется переменная s ?
Да и правда S не нужно. Но этот код просто дублирует первый канал. а в wav файле не всегда так. Вот когда изначально было, тогда где-то в середине уже расходились значения каналов. В этом то и суть двух каналов Так должно быть, разве нет? Хотя есть и недоразумение: в том Hex Editor Neo и правда дублируются каналы. Хотя я точно помню, что когда я первый раз использовал ваш первоначальный код, каналы не везде, но расходились значениями, или так как раз не должно было быть?
Да и правда S не нужно. Но этот код просто дублирует первый канал. а в wav файле не всегда так. Вот когда изначально было, тогда где-то в середине уже расходились значения каналов. В этом то и суть двух каналов Так должно быть, разве нет? Хотя есть и недоразумение: в том Hex Editor Neo и правда дублируются каналы. Хотя я точно помню, что когда я первый раз использовал ваш первоначальный код, каналы не везде, но расходились значениями, или так как раз не должно было быть?
Этот код не дублирует первый канал, а выдаёт то что содержится в wav-файле и если там идут одинаковые значения для левого и правого канала, то что же должно выводиться?
Этот код не дублирует первый канал, а выдаёт то что содержится в wav-файле и если там идут одинаковые значения для левого и правого канала, то что же должно выводиться?
Да, правда. Попробовал гигантский wav и там правда есть расходимость в каналах. 2 вопроса снято! Остался 3: все же как теперь записать значения? И не записывать вручную это
Код:
NumSamples := 1079;
и это
Код:
Sample := 1111;
. Что бы они сами заполнялись, как вы сказали, используя массив. Это для меня непосильная задача. Вот наверняка почти весь исходный код:
Код:
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;
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;
TWaveHeaderChank = record
wFormatTag : Smallint;
wChannels : WORD;
wSamplesPerSec : Cardinal;
wAvgBytesPerSec: Cardinal;
wBlockAlign : WORD;
wBitsPerSample : WORD;
wcbSize : WORD;
end;
TWaveResult = record
ERROR : WORD;
wAvgBytesPerSec: Cardinal;
wBitsPerSample : WORD;
wChannels : WORD;
Data : TMemoryStream;
end;
var
Form1: TForm1;
TxtFile : TextFile;
i : integer;
sample: Int64;
SampleSize, chanel, n: Integer;
s: String;
s1: String;
Ini:Tinifile;
language:string;
Handled: Boolean;
implementation
{$R *.dfm}
{$R WindowsXP.res}
uses math, Unit2;
Function ReadWave(FileName : AnsiString) : TWaveResult;
var
f : TFileStream;
wFileSize : Cardinal;
wChankSize : Cardinal;
ID : array[0..3] of Char;
Header : TWaveHeaderChank;
Begin
FillChar(Result, SizeOf(Result), 0);
Try
f := TFileStream.Create(FileName, fmOpenRead);
f.Seek(0, soFromBeginning);
f.ReadBuffer(ID[0], 4);
If String(ID) <> 'RIFF'
then
Begin
Result.ERROR := IncorectFileFormat;
f.Free;
exit;
end;
Form1.memo1.Lines.Add(String(ID));
f.ReadBuffer(wFileSize, 4);
Form1.memo1.Lines.Add('' + intToStr(wFileSize));
if f.size <> (wFileSize + 8)
then
Begin
Result.ERROR := FileCorrupt;
f.Free;
exit;
end;
f.ReadBuffer(ID[0], 4);
Form1.memo1.Lines.Add(String(ID));
if String(ID) <> 'WAVE'
then
Begin
Result.ERROR := IncorectFileFormat;
f.Free;
exit;
end;
wChankSize := 0;
repeat
f.Seek(wChankSize, soFromCurrent);
f.ReadBuffer(ID[0], 4);
Form1.memo1.Lines.Add(String(ID));
f.ReadBuffer(wChankSize, 4);
if wChankSize > High(integer)
then
Begin
Result.ERROR := DataError;
f.Free;
exit;
end;
Form1.memo1.Lines.Add('' + intToStr(wChankSize));
until (String(ID)='fmt ') or (String(ID)='data');
if String(ID)='data'
then
Begin
Result.ERROR := HeaderError;
f.Free;
exit;
end;
f.ReadBuffer(Header, Min(wChankSize, SizeOf(TWaveHeaderChank)));
Form1.memo1.Lines.Add('' + intToStr(Header.wFormatTag));
Form1.memo1.Lines.Add('' + intToStr(Header.wChannels));
Form1.memo1.Lines.Add('' + intToStr(Header.wSamplesPerSec));
Form1.memo1.Lines.Add('' + intToStr(Header.wAvgBytesPerSec));
Form1.memo1.Lines.Add('' + intToStr(Header.wBlockAlign));
Form1.memo1.Lines.Add('' + intToStr(Header.wBitsPerSample));
if wChankSize > SizeOf(TWaveHeaderChank)
then
f.Seek(wChankSize - SizeOf(TWaveHeaderChank), soFromCurrent);
if wChankSize >= SizeOf(TWaveHeaderChank)
then
Form1.memo1.Lines.Add('' + intToStr(Header.wcbSize));
wChankSize := 0;
repeat
f.Seek(wChankSize, soFromCurrent);
f.ReadBuffer(ID[0], 4);
Form1.memo1.Lines.Add(String(ID));
f.ReadBuffer(wChankSize, 4);
Form1.memo1.Lines.Add('' + intToStr(wChankSize));
until String(ID)='data';
//Попытка считать Сэмплы
if Header.wFormatTag<>1 then
begin
Form1.Memo1.Lines.Add('ОШИБКА! Я умею читать wav-файлы только в формате PCM, а этот файл в формате 0x'+IntToHex(Header.wFormatTag, 4));
end;
SampleSize:=(Header.wBitsPerSample+7) div 8;
if SampleSize>SizeOf(sample) then
begin
Form1.Memo1.Lines.Add('ОШИБКА! Слишком большой размер сэмпла ('+IntToStr(SampleSize)+' байт)');
Exit;
end;
if Header.wChannels=0 then
begin
Form1.Memo1.Lines.Add('ОШИБКА! Нет каналов');
Exit;
end;
Form1.Memo1.WordWrap:=False;
Form1.Memo1.ScrollBars:=ssBoth;
sample:=0;
i:=0;
while wChankSize>=(SampleSize*Header.wChannels) do
begin
if Header.wBlockAlign>0 then
begin
n:=f.Position mod Header.wBlockAlign;
if n>0 then
begin
n:=Header.wBlockAlign-n;
f.Seek(n, soFromCurrent);
Dec(wChankSize, n);
if wChankSize<(SampleSize*Header.wChannels) then Break;
end;
end;
Inc(i);
s1:='';
for chanel := 1 to Header.wChannels do
begin
f.ReadBuffer(sample, SampleSize);
Dec(wChankSize, SampleSize);
s1:=s1+IntToHex(sample, SampleSize*2);
end;
Form1.Memo1.Lines.Add(s1);
end;
exit;
f.Free;
Except
Result.ERROR := ReadError;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
r : TWaveResult;
begin
if opendialog1.Execute
then
r := ReadWave(opendialog1.FileName);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if SaveDialog1.Execute then
Form1.Memo1.Lines.SaveToFile(Form1.SaveDialog1.FileName + '.txt');
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
if OpenDialog2.Execute then
Form1.Memo2.Lines.LoadFromFile(Form1.OpenDialog2.FileName + '');
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Memo1.Clear;
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
Memo2.Clear;
end;
procedure WriteWav(const FileName: String);
type
TMassiv = array of array of Integer;
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;
Massiv: TMassiv;
begin
NumSamples := 1079; {Massiv[I, J];}
BytsPerSample := 2;
Header.ChunkID := 'RIFF';
Header.ChunkSize := StrToInt(Form1.Memo2.Lines[1]);
Header.Format := 'WAVE';
Header.Subchunk1ID := 'fmt ';
Header.Subchunk1Size := StrToInt(Form1.Memo2.Lines[4]);
Header.AudioFormat := $0001;
Header.NumChannels := StrToInt(Form1.Memo2.Lines[6]);
Header.SampleRate := StrToInt(Form1.Memo2.Lines[7]);
Header.ByteRate := StrToInt(Form1.Memo2.Lines[8]);
Header.BlockAlign := StrToInt(Form1.Memo2.Lines[9]);
Header.BitsPerSample := StrToInt(Form1.Memo2.Lines[10]);
Header.Subchunk2ID := 'data';
Header.Subchunk2Size := StrToInt(Form1.Memo2.Lines[12]);
fs := TFileStream.Create('New File.wav',fmCreate);
try
fs.WriteBuffer(Header, SizeOf(Header));
for I := 1 to NumSamples do
begin
for J := 1 to Header.NumChannels do
begin
Sample := 1111;
fs.WriteBuffer(Sample, BytsPerSample);
end;
end;
finally
fs.Free;
end;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
if SaveDialog2.Execute then
begin
WriteWav(SaveDialog2.FileName);
end;
end;
end.
Да, правда. Попробовал гигантский wav и там правда есть расходимость в каналах. 2 вопроса снято! Остался 3: все же как теперь записать значения? И не записывать вручную это
Код:
NumSamples := 1079;
и это
Код:
Sample := 1111;
. Что бы они сами заполнялись, как вы сказали, используя массив. Это для меня непосильная задача
Чтобы процедура/функция могла возвращать несколько результатов (вместо одного) можно использовать структуру (запись).
У вас функция ReadWave для возвращения результата уже использует структуру такого вида:
Код:
type
TWaveResult = record
ERROR : WORD;
wAvgBytesPerSec: Cardinal;
wBitsPerSample : WORD;
wChannels : WORD;
Data : TMemoryStream;
end;
Вот эту структуру можно дополнить нужными параметрами и в самой функции вместе с (или вместо) выводом этой информации в Memo записывать в эту структуру. А потом эту же структуру давать в качестве параметра процедуре WriteWav, которая и будет из неё читать нужные параметры.
Вот эту структуру можно дополнить нужными параметрами и в самой функции вместе с (или вместо) выводом этой информации в Memo записывать в эту структуру. А потом эту же структуру давать в качестве параметра процедуре WriteWav, которая и будет из неё читать нужные параметры.
можно растолковать мне, какими именно можно параметрами дополнить структуру result?
можно растолковать мне, какими именно можно параметрами дополнить структуру result?
Не структуру result, а структуру TWaveResult.
Дополнять нужно теми параметрами, которые можно прочитать из wav-файла в функции ReadWave, и которые нужно потом передать в процедуру WriteWav.