Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.07.2012, 01:56   #1
JekaDefer
Форумчанин
 
Регистрация: 07.04.2009
Сообщений: 112
По умолчанию Проблема с динамическим массивом...

есть у кого соображения как сделать чтоб с выделенными жирным и подчеркнутым строчками работал данный код...
Код:
unit Unit1;

interface

uses
  Windows, Forms, MMSystem, Classes, Controls, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  const
  sps	= 8000;	// samples per second
  freq1	= 1000;	 	// signal frequency (Hz)
  freq2	= 1000;	 	// signal frequency (Hz)
  freq3	= 1000;	 	// signal frequency (Hz)
  time1	= 1000;		// time of signal (ms)
  time2	= 1000;		// time of signal (ms)
  time3	= 1000;		// time of signal (ms)
  Volume1 = 32767;
  Volume2 = 32767;
  Volume3 = 32767;

type
  int16 = smallint;

var
  Form1: TForm1;
  hdr: array[0..2] of WAVEHDR;
  //second: array[0..2, 0..sps-1] of int16;	// full second
  second: array of array of int16;	// full second
implementation

{$R *.dfm}
procedure prepareSine();
var
  i, nSamples: Integer;
  angle, delta: double;
begin
  nSamples := sps * time1 div 1000;	// signal length in samples
  //
  angle := 0;
  delta := (freq1 / sps) * 2 * Pi;	// how much in one sample
  //
  for i := 0 to nSamples - 1 do begin
    //
    second[0, i] := random(Volume1*2-Volume1);//round(sin(angle) * Volume1);
    angle := angle + delta;
  end;

  nSamples := sps * time2 div 1000;	// signal length in samples
  //
  angle := 0;
  delta := (freq2 / sps) * 2 * Pi;	// how much in one sample
  //
  for i := 0 to nSamples - 1 do begin
    //
    second[1, i] := round(sin(angle) * Volume2);
    angle := angle + delta;
  end;

  nSamples := sps * time3 div 1000;	// signal length in samples
  //
  angle := 0;
  delta := (freq3 / sps) * 2 * Pi;	// how much in one sample
  //
  for i := 0 to nSamples - 1 do begin
    //
    second[2, i] := round(sin(angle) * Volume3);
    angle := angle + delta;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
  wout: hWaveOut;
  fmt: tWAVEFORMATEX;
begin
  SetLength(second, 3, sps);
  prepareSine();
  //
  With fmt do
  Begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := 1;
    nSamplesPerSec := SPS;
    wBitsPerSample := 16;
    nBlockAlign := nChannels*wBitsPerSample div 8;
    nAvgBytesPerSec := nSamplesPerSec*nBlockAlign;
    cbSize := 0;
  End;
  //
  WaveOutOpen(@wout, cardinal(-1), @fmt, 0, 0, 0);
  if (0 <> wout) then
  begin
    //
    for i := 0 to 2 do
    begin
      //
      fillChar(hdr[i], sizeof(hdr[i]), #0);
      hdr[i].lpData := @second[i];
      hdr[i].dwBufferLength := sizeof(second[i]);
      //
      waveOutPrepareHeader(wout, @hdr[i], sizeof(hdr[i]));
      WaveOutWrite(wout, @hdr[i], sizeof(hdr[i]));
    end;
    //
    //Sleep(3100);	// sleep for 3 seconds
    //
    waveOutUnprepareHeader(wout, @hdr, sizeof(TWAVEHDR));
    WaveOutClose(wout);
  end;
end;

end.
JekaDefer вне форума Ответить с цитированием
Старый 06.07.2012, 07:29   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
есть у кого соображения
Есть. Вставить код в приложение и запустить на выполнение.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 06.07.2012, 10:57   #3
Somebody
Участник клуба
 
Регистрация: 08.10.2007
Сообщений: 1,185
По умолчанию

Возможно, @second[i] надо заменить на @second[i][0].
Somebody вне форума Ответить с цитированием
Старый 06.07.2012, 11:04   #4
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Обьямите тип:
Код:
TMultiInt16=array of array of Int16;
только потом можно будет обьявить переменную этого типа и с ней работать.
Человек_Борща вне форума Ответить с цитированием
Старый 06.07.2012, 11:15   #5
Somebody
Участник клуба
 
Регистрация: 08.10.2007
Сообщений: 1,185
По умолчанию

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
Обьямите тип:
Код:
TMultiInt16=array of array of Int16;
только потом можно будет обьявить переменную этого типа и с ней работать.
Не обязательно, можно и так. Объявлять надо, если динамический массив передаётся функции как параметр, потому что там array of ... - это открытый массив.
Somebody вне форума Ответить с цитированием
Старый 06.07.2012, 13:07   #6
Прик
Форумчанин
 
Регистрация: 08.09.2010
Сообщений: 880
По умолчанию

Указателем на элемент динамического массива должен быть первый элемент и функция SizeOf не применима к вложенным в массив последовательностям. Ее надо тоже заменить. Например, как ниже показано.
Код:
var
  hdr: WAVEHDR;

procedure TForm1.Button1Click(Sender: TObject);
var
  I, J: integer;
  wout: hWaveOut;
  fmt: tWAVEFORMATEX;
begin
  SetLength(second, 3, sps);
  prepareSine();

  with fmt do Begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := 1;
    nSamplesPerSec := SPS;
    wBitsPerSample := 16;
    nBlockAlign := nChannels*wBitsPerSample div 8;
    nAvgBytesPerSec := nSamplesPerSec*nBlockAlign;
    cbSize := 0;
  end;

  WaveOutOpen(@wout, cardinal(-1), @fmt, 0, 0, 0);
  if (0 <> wout) then begin
    for I := 0 to 2 do begin
      hdr.lpData := @second[I][0];
      hdr.dwBufferLength := sps;

      waveOutPrepareHeader(wout, @hdr, sizeof(hdr));
      WaveOutWrite(wout, @hdr, sizeof(hdr));
      Sleep(2100);	
    end;

    waveOutUnprepareHeader(wout, @hdr, sizeof(TWAVEHDR));
    VirtualFree(@second,0,MEM_RELEASE);
    WaveOutClose(wout);
  end;
  second := nil;
end;
Так работает.
Прик вне форума Ответить с цитированием
Старый 06.07.2012, 14:50   #7
JekaDefer
Форумчанин
 
Регистрация: 07.04.2009
Сообщений: 112
По умолчанию

В общем пересмотрел код и решил сделать без объявления динамического массива на все "секунды" звуковой дорожки и обойтись только двумерным статическим массивом Second: array[0..1, 0..7999] of int16. Задача вообще всего этого: есть одномерный массив AllSamples, в котором сэмплы на всю звуковую дорожку(т.е. не на одну секунду а на все) и вот нужно теперь чередуя Second[0, 0..7999] и Second[1, 0..7999] отыграть все сэмплы массива AllSamples. Попробовал так:
Код:
WaveOutOpen(@wout, cardinal(-1), @fmt, 0, 0, 0);
  if (0 <> wout) then
  begin
    CheckSec:= False;
    For i:= 0 to nBlocks-1 do
    Begin
      if CheckSec then CurSec:= 1 else CurSec:= 0;

      For j:= 0 to SPS-1 do
      Begin
        if (i = nBlocks-1) and (j+SPS*i > Length(AllSamples)-1) then Second[CurSec, j]:= 0 else Second[CurSec, j]:= AllSamples[j+(SPS)*i];
      End;

      fillChar(hdr[0], sizeof(hdr[CurSec]), #0);
      hdr[CurSec].lpData := @second[CurSec];
      hdr[CurSec].dwBufferLength := sizeof(second[CurSec]);

      waveOutPrepareHeader(wout, @hdr[CurSec], sizeof(hdr[CurSec]));
      WaveOutWrite(wout, @hdr[CurSec], sizeof(hdr[CurSec]));
      CheckSec:= NOT CheckSec;
    End;
    waveOutUnprepareHeader(wout, @hdr, sizeof(TWAVEHDR));
    WaveOutClose(wout);
  end;
Сам массив Second заполняется весь как надо и и если на последней секунде дорожка кончилась то остаток заполняется нулями. то есть все как надо, но вот как теперь правильно указать на этот чередующийся массив головке?
JekaDefer вне форума Ответить с цитированием
Старый 06.07.2012, 15:16   #8
Прик
Форумчанин
 
Регистрация: 08.09.2010
Сообщений: 880
По умолчанию

И проблема в чем? В какой строке?

А зачем тогда два массива? Почему нельзя обойтись одним? Все равно каждый раз один из них надо заполнять из исходного.
И, наверное, вообще можно без заполнения промежуточного массива делать.
@AllSamples[CurrBlock] даст указатель на очередную порцию сэмплов (где CurrBlock - индекс начала очередного блока в исходном массиве), а размер - это всегда SPS (ну, кроме последнего блока, размер которого можно рассчитать).

Последний раз редактировалось Прик; 06.07.2012 в 15:22.
Прик вне форума Ответить с цитированием
Старый 06.07.2012, 18:54   #9
JekaDefer
Форумчанин
 
Регистрация: 07.04.2009
Сообщений: 112
По умолчанию

Ну у меня проблемы вчера возникли при проигрывании динамического массива, так и не смог справиться. Вот придумал вроде идеальный вариант по крайней мере мне так кажется. надо терь как то сделать чтоб игрался именно массив Second - так меньше памяти занимать будет. массив Sacond в данном примере чередуясь заполняется так как нужно я проверил.. Но вот проигрывается какая то чушь если превышает более 1 сек.. просто ведать я как то не так указываю или надо чтото очистить где то... но как?
JekaDefer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
проблема с динамическим массивом Noob(c++) Общие вопросы C/C++ 56 02.08.2012 23:09
Проблема с динамическим массивом TheKnyazz Общие вопросы C/C++ 3 28.04.2009 18:37
Проблема с динамическим массивом dee_lv Помощь студентам 7 09.06.2008 16:58
проблема с динамическим массивом romeo007.06 Общие вопросы Delphi 1 03.04.2008 20:18
проблема с динамическим массивом kommunist Помощь студентам 6 11.11.2007 21:18