Показать сообщение отдельно
  #41  
Старый 31.08.2012, 02:55
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Dmitry_DM
poli-smen, я все сделал и у меня все работает, как я хотел. Но в то время пока я занимался медиаплеером и графиками, (по чистой случайности заметил), перестала работать ЗАПИСЬ нового wav. Причину я, скорее всего, вычислил. Это идентификатор NumSamples. Он стал находится в
Код:
TWavInfo = record
    WaveFormat: TWaveFormat;
    NumSamples: Integer;
    MaxAmplitude: Integer;
    Samples: packed array of array of Smallint;
end;
Я так понял это нужно для построения графика. Но перестала работать запись, просто кнопка не работает.
Я заметил в процедуре чтения эту новую строчку:
Код:
WavInfo.NumSamples := LongInt(NumSamples);
Это просто преобразование типов (так как локальная переменная NumSamples является беззнаковым целым, а поле WavInfo.NumSamples целое со знаком), но в процедуре чтения не только это изменилось.
Самое главное изменение это то, что в массиве Samples поменялись местами размерности. Это изменение связано с особенностью реализации динамических массивов в Delphi, а именно то что:
Код:
  SetLength(Samples, 10000000, 2); // такая команда съест значительно больше памяти
  SetLength(Samples, 2, 10000000); // чем такая
А так как у звукового файла количество каналов невелико (обычно 1 или 2), а сэмплов наоборот может быть довольно значительное количество, то имело смысл сделать первой размерностью именно номер канала, а не сэмпла, как было до этого. Из-за этого изменения теперь нельзя получить количество сэмплов таким образом:
Код:
  NumSamples := Length(WavInfo.Samples);
Вместо этого в структуру TWavInfo было добавлено новое поле NumSamples, которое теперь и нужно читать, чтобы узнать количество сэмплов:
Код:
  NumSamples := WavInfo.NumSamples;
Ну и конечно, в связи с изменением порядка размерностей в массиве Samples теперь к его элементам нужно обращаться "наоборот":
Код:
  // Т.е. вместо:
  fs.WriteBuffer(WavInfo.Samples[I - 1, J - 1], BytsPerSample);
  // нужно писать так:
  fs.WriteBuffer(WavInfo.Samples[J - 1, I - 1], BytsPerSample);
Кроме того, в структуру TWavInfo добавлено поле MaxAmplitude в которое процедура чтения записывает максимальное значение амплитуды звука (это значение потом используется для нормального масштабирования при прорисовке), ну и у массива Samples поменялся тип его элементов: вместо беззнакового (Word) теперь используется знаковый (Smallint) двухбайтовый тип, так как сэмплы в действительности и являются числами со знаком (по крайней мере в формате PCM это именно так).

Цитата:
Сообщение от Dmitry_DM
Код записи:
Код:
procedure WriteWav(const FileName: string; const WavInfo: TWavInfo);
...
var
  Header: THeader;
  NumSamples, BytsPerSample, I, J: Longword;
  fs: TFileStream;
begin
  NumSamples := LongInt(NumSamples); //это я изменил, думал поможет, нет!
...
Нет, эта команда тут лишена смысла.

В программе рисования звуковой волны процедура сохранения была не нужна, поэтому её я не переделывал (и не использовал), но теперь у тебя есть вся информация для её переделки.
Ответить с цитированием