Форум по Delphi программированию



Вернуться   Форум по Delphi программированию > Все о Delphi > Мультимедиа
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #16  
Старый 26.09.2012, 18:23
Dmitry_DM Dmitry_DM вне форума
Активный
 
Регистрация: 07.08.2012
Сообщения: 258
Версия Delphi: Delphi 7
Репутация: 11
По умолчанию

Цитата:
Сообщение от poli-smen
Где я писал что Sample не участвует в вычислениях? Я писал что в вычислениях не участвуют сэмплы из wav-файла.
Я и не писал что в выводе в файл они не участвуют. Но после вывода в файл идут вычисления, и вот в вычислениях они уже не участвуют.
Можно в начале процесса, но лучше сразу перед подсчётом суммы, т.е. так как это сделано для переменной S2.
Нет, нет. Я не писал что нужно заменить одну строчку на другую. Заменять нужно весь цикл на ту строчку. Т.е. заменить это:
Код:
for Sample := 1 to NumSamples do
  begin
    s:=s+Sample;
  end;
на это:
Код:
s := s + (NumSamples + 1) * NumSamples div 2;
И если переменная S должна быть проинициализирована нулём, то строчку S:=0; в твоём случае нужно поставить сразу перед циклом, а в моём случае упростить заменяющую строчку на такую:
Код:
s := (NumSamples + 1) * NumSamples div 2;
Да, я там забыл квадратный корень из M1. В программе во время теста исправил, а при отправке на форум исправить забыл
Смотри во вложении тестовый пример. Там левая кнопка выводит в левый Memo результат работы твоего кода, а правая кнопка выводит в правый Memo результат работы моего кода. Результаты не должны отличаться. Для вычислений открывать wav-файл не нужно, достаточно ввести в поле ввода значение NumSamples (количество сэмплов), которые ты можешь получить открыв wav-файл в своей программе, ну и заодно убедиться, что результаты работы в твоей программе и в этом тестовом примере не отличаются и не зависят от самого wav-файла.
И ещё обрати внимание, что у тебя там происходит переполнение: если сложить все числа от 1 до 398592 (т.е. 1+2+3+...+398591+398592), то должно получиться огромное число 79437990528, а у тебя показывает всего лишь:Явное переполнение (18 раз). Это всё потому что максимальное число которое можно записать в переменную типа LongWord равно 4294967295. Чтобы не было переполнения нужно использовать более вместительные типы Int64 или Extended.
Ну, по моему, это и так понятно - нужно чтобы в вычислении участвовали также и сэмплы из wav-файла, а не только NumSamples.
Конечно должны учавствовать и сами сэмплы, я это сам знаю. Да, действительно результаты одинаковые, хотя вы не используете сэмплы из wav файла. А как тогда их задествовать? Вы же, наверное, уже вкурсе что я делаю? И догадываетесь про мои дальнейшее манипуляции с файлом. Но пока мне нужно вычислить эксцесс и ассимтрию. Вы знаете эти формулы, в математическом виде? Если нет, я могу их вам написать, как они есть, и тогда можно будет воплотить это на языке програмирования. Спасибо за то, что откликнулись, прониклись моей проблемой и за то, что помогаете. Спасибо!
Ответить с цитированием
  #17  
Старый 27.09.2012, 05:21
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Dmitry_DM
Конечно должны учавствовать и сами сэмплы, я это сам знаю. Да, действительно результаты одинаковые, хотя вы не используете сэмплы из wav файла. А как тогда их задествовать?
Сэмплы находятся в массиве, поэтому чтобы их задействовать в вычислениях нужно просто брать их из этого массива.
Вот например этот цикл:
Код:
for Sample := 1 to NumSamples do
  begin
    s:=s+Sample;
  end;
Здесь переменная Sample в цикле принимает значения от 1 до NumSamples и эти числа суммируются. Получается просто сумма натуральных чисел т.е. 1+2+3+4+5+6+.....+NumSamples. А это вообще нужно? Подозреваю что нет. Здесь скорее всего нужно посчитать сумму всех сэмплов, а не сумму чисел натурального ряда. Исходя из этих догадок этот цикл преобразуется в такой:
Код:
for Index := 1 to NumSamples do
  begin
    Sample := WavInfo.Samples[НомерКанала - 1, Index - 1]; // Читаем из массива очередной сэмпл
    s:=s+Sample; // А вот теперь в переменной Sample действительно сэмпл wav-файла и его можно суммировать
  end;
Всё то же самое и с остальными циклами.
Цитата:
Сообщение от Dmitry_DM
Вы же, наверное, уже вкурсе что я делаю? И догадываетесь про мои дальнейшее манипуляции с файлом.
Нет, не догадываюсь.
Цитата:
Сообщение от Dmitry_DM
Но пока мне нужно вычислить эксцесс и ассимтрию. Вы знаете эти формулы, в математическом виде? Если нет, я могу их вам написать, как они есть, и тогда можно будет воплотить это на языке програмирования.
Нет, формул я таких не знаю, но подозреваю что это эксцесс, а это ассимтрия.
Ответить с цитированием
Этот пользователь сказал Спасибо poli-smen за это полезное сообщение:
Dmitry_DM (27.09.2012)
  #18  
Старый 27.09.2012, 17:46
Dmitry_DM Dmitry_DM вне форума
Активный
 
Регистрация: 07.08.2012
Сообщения: 258
Версия Delphi: Delphi 7
Репутация: 11
По умолчанию

А можно так попробовать? Теоретический это правильно?
Код:
Z: array [0..10000,0..10000] of Int64;
      Sample := 0;
      S:=0;
      Sl:=tStringlist.Create;
      for I := 1 to NumSamples do
      begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
        begin
          fs.ReadBuffer(Sample, BytsPerSample);
         case BytsPerSample of
            1: Sample := ShortInt(Sample);
            2: Sample := SmallInt(Sample);
          end;
      WavInfo.Samples[J - 1, I - 1] := Sample;
      if Abs(Sample) > WavInfo.MaxAmplitude then WavInfo.MaxAmplitude := Abs(Sample);

         sl.Add(IntToStr(Sample));


         z[j,i]:=Sample;


        end;
      end;
    WavInfo.NumSamples := LongInt(NumSamples);
    end;
          sl.SaveToFile('Samples.txt');
         SL.Free;

    for I := 1 to NumSamples do
      begin
        s:=(s+z[j,i]);
      end;

    Xch:=S/NumSamples;

    S2:=0;
    for I := 1 to NumSamples do
    begin
    S2:=s2+Sqr(z[j,i]-Xch);
    end;
    M1:=Sqrt((s2/NumSamples)*(s2/NumSamples)*(s2/NumSamples));
//
    S2:=0;
    for I := 1 to NumSamples do
    begin
    S2:=s2+(z[j,i]-Xch)*(z[j,i]-Xch)*(z[j,i]-Xch);
    end;
    M2:=(s2/NumSamples);
//
    S2:=0;
    for I := 1 to NumSamples do
    begin
    S2:=s2+sqr(z[j,i]-Xch);
    end;
    M3:=Sqr(s2/NumSamples);
//
    S2:=0;
    for I := 1 to NumSamples do
    begin
    S2:=s2+sqr(Sqr(z[j,i]-Xch));
    end;
    M4:=(s2/NumSamples);

    A:=M2/m1;
    E:=m4/m3;
Ответить с цитированием
  #19  
Старый 28.09.2012, 01:46
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Dmitry_DM
А можно так попробовать? Теоретический это правильно?
Код:
Z: array [0..10000,0..10000] of Int64;
.....
А какой смысл вводить посредника в виде массива z?
  1. Программа уже загрузила сэмплы звукового файла в массив WavInfo.Samples, а теперь мы их ещё копируем в массив z - получаем как минимум двойной расход памяти на пустом месте
  2. Первая размерность массива отвечает за количество каналов. Зачем здесь зарезервировано столько каналов? Бывает "моно" (1 канал), бывает "стерео" (2 канала), бывает ещё "4+1", "5+1", ну пусть 10 каналов, но десять тысяч это уже что-то невероятное - получаем ещё бесполезный перерасход памяти
  3. Вторая размерность массива отвечает за количество сэмплов. В массиве z зарезервировано память всего под десять тысяч семплов, а ведь недавно ты открывал звуковой файл в котором было 398592 сэмплов - в этот массив он никак не влезет
  4. Почему тип элементов массива z выбран Int64? Звуковые файлы в формате WAVEFORMATEX PCM бывают либо 8-битные (1 байт), либо 16-битные (2 байта), а массив z резервирует для них по 64 бита (8 байт) - опять бесполезный перерасход памяти
И ещё, где инициализируется переменная J вот в этом цикле?:
Код:
    for I := 1 to NumSamples do
      begin
        s:=(s+z[j,i]);
      end;
Да и в следующих циклах тоже?
Ответить с цитированием
  #20  
Старый 28.09.2012, 11:00
Dmitry_DM Dmitry_DM вне форума
Активный
 
Регистрация: 07.08.2012
Сообщения: 258
Версия Delphi: Delphi 7
Репутация: 11
По умолчанию

Цитата:
Сообщение от poli-smen
А какой смысл вводить посредника в виде массива z?
  1. Программа уже загрузила сэмплы звукового файла в массив WavInfo.Samples, а теперь мы их ещё копируем в массив z - получаем как минимум двойной расход памяти на пустом месте
  2. Первая размерность массива отвечает за количество каналов. Зачем здесь зарезервировано столько каналов? Бывает "моно" (1 канал), бывает "стерео" (2 канала), бывает ещё "4+1", "5+1", ну пусть 10 каналов, но десять тысяч это уже что-то невероятное - получаем ещё бесполезный перерасход памяти
  3. Вторая размерность массива отвечает за количество сэмплов. В массиве z зарезервировано память всего под десять тысяч семплов, а ведь недавно ты открывал звуковой файл в котором было 398592 сэмплов - в этот массив он никак не влезет
  4. Почему тип элементов массива z выбран Int64? Звуковые файлы в формате WAVEFORMATEX PCM бывают либо 8-битные (1 байт), либо 16-битные (2 байта), а массив z резервирует для них по 64 бита (8 байт) - опять бесполезный перерасход памяти
И ещё, где инициализируется переменная J вот в этом цикле?:
Код:
    for I := 1 to NumSamples do
      begin
        s:=(s+z[j,i]);
      end;
Да и в следующих циклах тоже?
Я так и думал, что так не правильно. А тем способом, что вы писали, он компилируется успешно, но возникает ошибка доступа (access violation).

А вот так работает! Я думаю, так правильнее всего. Как вы считаете? И хочу отметить, что при расчетах асимметрия должна быть близко к 0, у меня -0,4(Ну ладно, такое отклонение реальное, но не "-" же), а эксцесс должен быть близко к 3, но у меня 28,7(Это вообще как понимать??) Вот вроде бы успешный код, при
Код:
  Sample, s: LongInt;
  NumSamples: LongWord;
  Xch, S2, M1, M2, M3, M4, A, E: Extended;
:
Код:
      
      Sample := 0;
      S:=0;

      Sl:=tStringlist.Create;
      for I := 1 to NumSamples do
      begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
        begin
          fs.ReadBuffer(Sample, BytsPerSample);
         case BytsPerSample of
            1: Sample := ShortInt(Sample);
            2: Sample := SmallInt(Sample);
          end;
      WavInfo.Samples[J - 1, I - 1] := Sample;
      if Abs(Sample) > WavInfo.MaxAmplitude then WavInfo.MaxAmplitude := Abs(Sample);

         sl.Add(IntToStr(Sample));

        end;
      end;
    WavInfo.NumSamples := LongInt(NumSamples);
    end;
          sl.SaveToFile('Samples.txt');
         SL.Free;

   for I := 1 to NumSamples do
      begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
       begin
        Sample := WavInfo.Samples[J - 1, I - 1];
        s:=(s+Sample);
       end;
      end;
    Xch:=S/NumSamples;
//
    S2:=0;
      for I := 1 to NumSamples do
    begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
      begin
    Sample := WavInfo.Samples[J - 1, I - 1];
    S2:=s2+Sqr(Sample-Xch);
      end;
     end;
     M1:=Sqrt((s2/NumSamples)*(s2/NumSamples)*(s2/NumSamples));
//

    S2:=0;
      for I := 1 to NumSamples do
    begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
      begin
    Sample := WavInfo.Samples[J - 1, I - 1];
    S2:=s2+(Sample-Xch)*(Sample-Xch)*(Sample-Xch);
      end;
    end;
     M2:=(s2/NumSamples);
//
    S2:=0;
      for I := 1 to NumSamples do
    begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
    begin
    Sample := WavInfo.Samples[J - 1, I - 1];
    S2:=s2+sqr(Sample-Xch);
    end;
    end;
     M3:=Sqr(s2/NumSamples);
//
    S2:=0;
      for I := 1 to NumSamples do
    begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
     begin
    Sample := WavInfo.Samples[J - 1, I - 1];
    S2:=s2+sqr(Sqr(Sample-Xch));
     end;
    end;
    M4:=(s2/NumSamples);
    A:=M2/m1;
    E:=m4/m3;
Но не может же быть:
Код:
S: -294637033
Xch: -739,194547306519
M1: 12680979913,2141
M2: -6053863801,8443
M3: 29571300156300,5
M4: 849049452165860
Asymmetry: -0,477397160414704
Excess: 28,7119419057725
MaxAmplitude: 24927
BytsPerSample: 2
NumSamples: 398592
Ниже txt с выведенными сэмплами.
Вложения
Тип файла: rar Samples.rar (731.0 Кбайт, 2 просмотров)

Последний раз редактировалось Dmitry_DM, 28.09.2012 в 14:05.
Ответить с цитированием
  #21  
Старый 30.09.2012, 21:13
Dmitry_DM Dmitry_DM вне форума
Активный
 
Регистрация: 07.08.2012
Сообщения: 258
Версия Delphi: Delphi 7
Репутация: 11
По умолчанию

poli-smen, так все-же так правильно будет или нет. По-моему так лучше всего. И еще такой вопрос: почему здесь
Код:
Sample := WavInfo.Samples[J - 1, I - 1];
именно [J - 1, I - 1]. Зачем -1 делать. Просто знать хочу.
Ответить с цитированием
  #22  
Старый 30.09.2012, 21:40
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Dmitry_DM
Я так и думал, что так не правильно. А тем способом, что вы писали, он компилируется успешно, но возникает ошибка доступа (access violation).
В моём способе "Access Violation" может возникнуть разве что если неправильно указать номер канала вот здесь:
Код:
Sample := WavInfo.Samples[НомерКанала - 1, Index - 1]; // Читаем из массива очередной сэмпл
Если у звукового файла всего 1 канал, то вместо "НомерКанала" можно подставлять только число 1. Если у звукового файла 2 канала, то вместо "НомерКанала" можно подставлять число 1 либо 2. Если же вместо "НомерКанала" поставить например 0, то после вычитания единицы получем несуществующий индекс -1 (минус один) и как следствие "Access Violation".
Цитата:
Сообщение от Dmitry_DM
А вот так работает! Я думаю, так правильнее всего. Как вы считаете?
Код:
....
   for I := 1 to NumSamples do
      begin
        for J := 1 to WavInfo.WaveFormat.nChannels do
       begin
        Sample := WavInfo.Samples[J - 1, I - 1];
        s:=(s+Sample);
       end;
      end;
    Xch:=S/NumSamples;
....
Тут наверно тоже не совсем правильно. В NumSamples хранится количество сэмплов в одном канале. Если в звуковом файле один канал, то всё правильно, если же в звуковом файле 2 канала, то в этих циклах просуммируется в 2 раза больше сэмплов чем указано в переменной NumSamples, но потом при вычислении Xch мы делим на NumSamples, а не на (NumSamples*2). А если я правильно понял - в переменной Xch должно вычисляться среднее арифметическое?
То же самое и в остальных циклах.
Цитата:
Сообщение от Dmitry_DM
И еще такой вопрос: почему здесь
Код:
Sample := WavInfo.Samples[J - 1, I - 1];
именно [J - 1, I - 1]. Зачем -1 делать. Просто знать хочу.
Так как в динамических массивах нумерация идёт от нуля и до Length-1, а здесь в циклах подсчёт идёт от 1 до Length, поэтому и вычитается единица.
Ответить с цитированием
Этот пользователь сказал Спасибо poli-smen за это полезное сообщение:
Dmitry_DM (01.10.2012)
  #23  
Старый 01.10.2012, 15:39
Dmitry_DM Dmitry_DM вне форума
Активный
 
Регистрация: 07.08.2012
Сообщения: 258
Версия Delphi: Delphi 7
Репутация: 11
По умолчанию

poli-smen, вот эти формулы, которые я использую. Вот формула для нахождения эксцесса: Только надо представить, что 3 нету.
g2 - у меня E;
m4 - m4;
m2(в квадрате) - m3;
n(общее кол.) - NumSamples;
X[i] - Sample;
X(вектор) - Xch;
Теперь формула для нахождения асимметрии:
g1 - у меня А;
m3 - m2;
m2(3/2) - m1;
n(общее кол.) - NumSamples;
X[i] - Sample;
X(вектор) - Xch;
Вот и все. По-моему так и вышло.
Ответить с цитированием
  #24  
Старый 01.10.2012, 16:03
Dmitry_DM Dmitry_DM вне форума
Активный
 
Регистрация: 07.08.2012
Сообщения: 258
Версия Delphi: Delphi 7
Репутация: 11
По умолчанию

Цитата:
Сообщение от poli-smen
В NumSamples хранится количество сэмплов в одном канале. Если в звуковом файле один канал, то всё правильно, если же в звуковом файле 2 канала, то в этих циклах просуммируется в 2 раза больше сэмплов чем указано в переменной NumSamples, но потом при вычислении Xch мы делим на NumSamples, а не на (NumSamples*2).
Так можно сделать?
Код:
if WavInfo.WaveFormat.nChannels = 2
     then Xch:=S/(NumSamples*2)
     else Xch:=S/NumSamples;
Ответить с цитированием
  #25  
Старый 01.10.2012, 16:13
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Dmitry_DM
Так можно сделать?
Код:
if WavInfo.WaveFormat.nChannels = 2
     then Xch:=S/(NumSamples*2)
     else Xch:=S/NumSamples;
Вместо этого лучше так:
Код:
Xch := S / (NumSamples * WavInfo.WaveFormat.nChannels)
Ответить с цитированием
  #26  
Старый 01.10.2012, 16:20
Dmitry_DM Dmitry_DM вне форума
Активный
 
Регистрация: 07.08.2012
Сообщения: 258
Версия Delphi: Delphi 7
Репутация: 11
По умолчанию

Цитата:
Сообщение от poli-smen
Вместо этого лучше так:
Код:
Xch := S / (NumSamples * WavInfo.WaveFormat.nChannels)
Хм.. Да, вы правы. так будет для всех случаев. А что на счет формул?
Ответить с цитированием
  #27  
Старый 02.10.2012, 05:42
Аватар для poli-smen
poli-smen poli-smen вне форума
Профессионал
 
Регистрация: 06.08.2012
Адрес: Кривой Рог
Сообщения: 1,791
Версия Delphi: Delphi 7, XE2
Репутация: 4415
По умолчанию

Цитата:
Сообщение от Dmitry_DM
Хм.. Да, вы правы. так будет для всех случаев. А что на счет формул?
Вроде правильно вычисляется. Только немного сбивает с толку странное переименование переменных (т.е. то что m3 это m2, m2(3/2) это m1, m2(в квадрате) это m3, ...).
И ещё я это всё сократил бы примерно так:
Код:
var
  Sample, s: LongInt;
  NumSamples, I, J, N: LongWord;
  Xch, S1, S2, M1, M2, M3, M4, A, E: Extended;
....
begin
....
  N := NumSamples * WavInfo.WaveFormat.nChannels; // Общее количество сэмплов

  Xch := 0;
  for I := 1 to NumSamples do
  begin
    for J := 1 to WavInfo.WaveFormat.nChannels do
    begin
      Xch := Xch + WavInfo.Samples[J - 1, I - 1];
    end;
  end;
  Xch := Xch / N; // Среднее арифметическое всех сэмплов

  M2 := 0;
  M3 := 0;
  M4 := 0;
  for I := 1 to NumSamples do
  begin
    for J := 1 to WavInfo.WaveFormat.nChannels do
    begin
      S1 := WavInfo.Samples[J - 1, I - 1] - Xch; // Отклонение от среднеарифметического
      S2 := Sqr(S1); // Квадрат отклонения от среднеарифметического
      M2 := M2 + S2; // Сумма квадратов
      M3 := M3 + S1 * S2; // Сумма кубов
      M4 := M4 + Sqr(S2); // Сумма 4 степени
    end;
  end;
  M2 := M2 / N;
  M3 := M3 / N;
  M4 := M4 / N;

  E := M4 / Sqr(M2);
  A := M3 / Sqrt(M2 * M2 * M2);
....
end;
Здесь переменные M2, M3, M4 получили своё оригинальное значение (т.е. как в формулах) и отсутствует кусок кода выводящий сэмплы в файл, так как он не имеет отношения к вычислениям формул.
Ответить с цитированием
Ответ



Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 06:48.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2021

ВКонтакте   Facebook   Twitter   Ссылка на Telegram