На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Микширование нескольких wav файлов в один с помощью c#
    Здравствуйте! Помогите разобраться, я почитал про описание формата wav, но похоже так и не понял) прошу разъяснить, если кто знает как...
    Суть вопроса в том, что у меня есть 3 wav файла: file1.wav(длиной 10 секунд), file2.wav(длиной 3 секунды), file3.wav(длиной 1,25 секунды). Мне нужно соединить их так, чтобы в итоге получился один out.wav файл длиной 10 секунд, при этом file2.wav играет с 5 по 8 секунду, а file3.wav играет с 7 по 8.25 секунды.
    Файл mono, 16 бит.

    Из описания формата wav, понимаю что нужно оставить заголовок от первого файла, а дальше нужно работать с data трех файлов. Только как их расположить? Если я их расположу последовательно, то получится конкатенация. А мне нужно именно смикшировать их. Кто может объяснить, как это сделать? если будет пример на c# даже кусочек, буду очень благодарен.
      В простейшем случае, микширование - сложение отсчётов из data разных файлов.
      Позиционирование в data по времени связано с частотой дискретизации. № отсчёта в data = частота дискретизации(Гц) * время(с).
        хм, не совсем понимаю про позиционирование по времени, это ведь справедливо для целых чисел? ну т.е. точно по секундам? а если мне нужно более точно, чтобы например data одного из файлов играла с 3.256 секунд?
        А можно еще показать небольшой пример на c# ?
          Цитата
          а если мне нужно более точно, чтобы например data одного из файлов играла с 3.256 секунд?

          Частота дискретизации прописана в разделе 'fmt ' wave.
          Например, 48000 Гц(отсчётов/с) * 3,256 с = 156 288 отсчётов.
            хм, а как работать с этими отсчетами?
            например, если я прочитаю wav файл таким образом:

            ExpandedWrap disabled
                          byte[] byteArray;
               
                          BinaryReader reader = new BinaryReader(waveFileStream);
               
                          int chunkID = reader.ReadInt32();
                          int fileSize = reader.ReadInt32();
                          int riffType = reader.ReadInt32();
                          int fmtID = reader.ReadInt32();
                          int fmtSize = reader.ReadInt32();
                          int fmtCode = reader.ReadInt16();
                          int channels = reader.ReadInt16();
                          int sampleRate = reader.ReadInt32();
                          int fmtAvgBPS = reader.ReadInt32();
                          int fmtBlockAlign = reader.ReadInt16();
                          int bitDepth = reader.ReadInt16();
               
                          int dataID = reader.ReadInt32();
                          int dataSize = reader.ReadInt32();
               
                          byteArray = reader.ReadBytes(dataSize);


            Получаю data в бинарном виде, как теперь можно работать с отсчетами?
              Вот примерный вывод данных одного из wav файлов, byteArray обрезал, т.к. слишком большие данные)

              ExpandedWrap disabled
                chunkID: 1179011410
                fileSize: 585664
                riffType: 1163280727
                fmtID: 544501094
                fmtSize: 16
                fmtCode: 1
                channels: 2
                sampleRate: 44100
                fmtAvgBPS: 176400
                fmtBlockAlign: 4
                bitDepth: 16
                dataID: 1635017060
                sampleRate: 44100
                dataSize: 585372
                byteArray: 0, 0, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 1, 0, 255, 255, 0, 0, 0, 0, 2, 0, 255, 255, 1, 0.................
                Цитата
                Получаю data в бинарном виде, как теперь можно работать с отсчетами?

                Отсчёт - 16 битное целое со знаком, в случае 16 битного звука.
                Отсчёты расположены последовательно в data. Если файл стерео, то отсчёты каналов (левый/правый) чередуются.
                Читайте не в бинарный массив, а в массив short(или как оно там в c# называется, 16 бит, целое со знаком).
                  А еще у меня вопрос, вот в моем примере:

                  ExpandedWrap disabled
                    sampleRate: 44100
                    dataSize: 585372
                    channels: 2
                    bitDepth: 16


                  Я нашел формулу, по которой можно найти количество отсчетов, т.е.
                  ExpandedWrap disabled
                    dataSize/(channels*bitDepth/8)=кол-во отсчетов


                  Отсюда получаю 146343 и вопрос такой, в один отсчет входит сразу и левый и правый? или один отсчет это только левый, а правый это уже второй?

                  Просто наткнулся на пример кода:
                  ExpandedWrap disabled
                                WavHeader Header = new WavHeader();
                                List<short> lDataList = new List<short>();
                                List<short> rDataList = new List<short>();
                     
                                using (FileStream fs = new FileStream(args[0], FileMode.Open, FileAccess.Read))
                                using (BinaryReader br = new BinaryReader(fs))
                                {
                                    
                                        Header.riffID = br.ReadBytes(4);
                                        Header.size = br.ReadUInt32();
                                        Header.wavID = br.ReadBytes(4);
                                        Header.fmtID = br.ReadBytes(4);
                                        Header.fmtSize = br.ReadUInt32();
                                        Header.format = br.ReadUInt16();
                                        Header.channels = br.ReadUInt16();
                                        Header.sampleRate = br.ReadUInt32();
                                        Header.bytePerSec = br.ReadUInt32();
                                        Header.blockSize = br.ReadUInt16();
                                        Header.bit = br.ReadUInt16();
                                        Header.dataID = br.ReadBytes(4);
                                        Header.dataSize = br.ReadUInt32();
                     
                                        for (int i = 0; i < Header.dataSize / Header.blockSize; i++)
                                        {
                                            lDataList.Add((short)br.ReadUInt16());
                                            rDataList.Add((short)br.ReadUInt16());
                                        }
                    }


                  И когда я его попробовал на своем wav файле, то у меня получилось что
                  ExpandedWrap disabled
                    lDataList.Count = rDataList.Count = 146343

                  Поэтому такой вопрос)

                  Добавлено
                  ошибся с формулой
                  ExpandedWrap disabled
                    dataSize/(channels*fmtBlockAlign/8)=кол-во отсчетов
                    Отсчёт(семпл в англ.) - это как бы мгновенное значение параметра в определенный момент времени. Во время записи звуковая карта измеряет напряжение на входе АЦП с частотой, называемой частотой дискретизации(или, что то же самое, через равные интервалы времени, называемые интервалом дискретизации), и представляет измеренные значения напряжения в виде 8/16/24/32 битных чисел. При воспроизведении происходит обратный процесс, звуковая карта выдает на ЦАП записанные значения(отсчёты) с той же частотой, что и при записи, а ЦАП восстанавливает исходный сигнал. Отсчёты многоканальной записи чередуются в блоке data wave файла.
                    Цитата
                    Отсюда получаю 146343 и вопрос такой, в один отсчет входит сразу и левый и правый?

                    В общем, да, "входит сразу и левый и правый". Но вопрос терминологии: можно ли называть отсчётом многоканального файла отсчёты всех каналов, - остаётся открытым.
                    146343 - это 146343 временные точки(или точки измерения). dataSize является производным от 146343(точки измерения), channels и bitDepth. А 146343 точки измерения, хоть и могут быть получены из dataSize путём математических вычислений, производным от dataSize не являются. С точки зрения физики процесса.

                    Допустим есть 3 временные точки, в которых измерены значения(взяты отсчёты) по 2-м каналам, разрядность данных 16 бит.
                    В data они располагаются так:
                    ExpandedWrap disabled
                       
                                      1-я точка              |              2-я точка                |                 3-я точка
                       2_байта_L_Channel   2_байта_R_Channel | 2_байта_L_Channel   2_байта_R_Channel | 2_байта_L_Channel   2_байта_R_Channel
                       <-----Sample-----><------Sample------>|
                       <-----------nBlockAlign-------------->|


                    nBlockAlign = channels*bitDepth/8 = 4 (байта).
                    datasize = 3(точки измерения) * nBlockAlign = 12 (байт).

                    И обратно, сколько точек в файле?
                    12(байт) / nBlockAlign = 12/4 = 3 точки.
                    Сообщение отредактировано: Prince -
                      Когда-то в сорок пятом что-то подобное делал. По памяти - сложение двух сэмплов может выдать значение, которое не помещается в 32678. "Обрезание" до 32768 может негативно сказываться на результирующем файле. Поэтому сначала надо пройтись по всем сэмплам и найти максимум суммы сэмплов, которая переваливает за эту отметку, после чего посчитать коэффициент, при умножении на который сумма влезает в 32768, и применять этот коэффициент при сложении сэмплов. Так же эффекта можно добиться деля сумму сэмплов на 2, т.е. беря среднее из двух сэмплов.

                      Как-то так, но помню очень смутно.
                        Частот файлов одинаковая? Если да, то тут все проще. Найти среднее значение (проще всего разделить значение каждого сэмпла на кол-во одновременно игрющих звуков и сложить их вместе). Конечно нужно учитывать сдвиг (как его вычислить, уже написано).

                        Если частоты разные, тут уже сложнее.
                        Сообщение отредактировано: DIS -
                          У меня точно такой же вопрос. Только с C# у меня никак не получается разобраться, с чего начать?
                          Как сложить семплы для определенного времени?
                          Цитата Prince @
                          Например, 48000 Гц(отсчётов/с) * 3,256 с = 156 288 отсчётов.


                          Может кто-нибудь показать примерный алгоритм, как можно подробнее? ну никак не догоню как с этим работать, но очень хочу понять =(
                          Частота файлов одинаковая.
                            Цитата
                            У меня точно такой же вопрос. Только с C# у меня никак не получается разобраться, с чего начать?

                            Цитата
                            Может кто-нибудь показать примерный алгоритм, как можно подробнее? ну никак не догоню как с этим работать, но очень хочу понять =(

                            Спросите как-нибудь иначе, и конкретней.
                            Сообщение отредактировано: Prince -
                              С чего начать?
                              1) Я так понял сначала нужно прочитать wav файлы в short? Как это правильно сделать?
                              Из кода выше:
                              ExpandedWrap disabled
                                            WavHeader Header = new WavHeader();
                                            List<short> lDataList = new List<short>();
                                            List<short> rDataList = new List<short>();
                                 
                                            using (FileStream fs = new FileStream(args[0], FileMode.Open, FileAccess.Read))
                                            using (BinaryReader br = new BinaryReader(fs))
                                            {
                                                
                                                    Header.riffID = br.ReadBytes(4);
                                                    Header.size = br.ReadUInt32();
                                                    Header.wavID = br.ReadBytes(4);
                                                    Header.fmtID = br.ReadBytes(4);
                                                    Header.fmtSize = br.ReadUInt32();
                                                    Header.format = br.ReadUInt16();
                                                    Header.channels = br.ReadUInt16();
                                                    Header.sampleRate = br.ReadUInt32();
                                                    Header.bytePerSec = br.ReadUInt32();
                                                    Header.blockSize = br.ReadUInt16();
                                                    Header.bit = br.ReadUInt16();
                                                    Header.dataID = br.ReadBytes(4);
                                                    Header.dataSize = br.ReadUInt32();
                                 
                                                    for (int i = 0; i < Header.dataSize / Header.blockSize; i++)
                                                    {
                                                        lDataList.Add((short)br.ReadUInt16());
                                                        rDataList.Add((short)br.ReadUInt16());
                                                    }
                                }

                              Я так понял это как раз ответ на мой вопрос? Это для стерео ?
                              2) Второй вопрос: теперь что-бы соединить таких 5 или 10 файлов, что нужно сделать? хотелось бы подробнее про позиционирование?
                              Нашел формулу для двух файлов, Z=A+B−AB, но как ее применить? особенно для стерео wav файлов?
                                Не в обиду, а вполне серьезно: вы понимаете, что и как хранится в wav? Формат wav вам известен/понятен? Как интепретировать данные из него - представляете хотя бы примерно?
                                Цитата
                                Я так понял сначала нужно прочитать wav файлы в short? Как это правильно сделать?

                                Правильнее, имхо, так http://msdn.microsoft.com/en-us/library/ms712835(VS.85).aspx. Но для конкретных случаев, можно и как в приведенном отрывке(если он рабочий).
                                wav файлы в short читать - некорректное выражение. Для хранения данных из wav можно/нужно выбирать подходящие типы, в зависимости от разрядности аудио. Для 16 бит подходит short, иначе говоря, целое двухбайтвое число со знаком. Для 8 бит - однобайтовое число без знака. Есть и другие типы семплов, нет смысла заморачиваться сейчас.
                                Разберитесь в форматом файла, что в нём вообще хранится.
                                Цитата
                                хотелось бы подробнее про позиционирование?

                                Да вроде подробно всё расписал.
                                round(время в секундах * Header.sampleRate) * Header.blockSize = позиция в блоке data.
                                // под round имеется в виду функция округления до целого. Как эта функция может выглядеть в C# - не знаю.
                                Цитата
                                Нашел формулу для двух файлов, Z=A+B−AB, но как ее применить?

                                Откуда такая формула?
                                Сообщение отредактировано: Prince -
                                  Спасибо большое, что сильно не ругаетесь.
                                  Ну примерно я представляю wav формат, первые 44 байта заголовок, а дальше данные.
                                  Для себя хочу все по пунктам разложить ход действий. Мне нужно соединить скажем 3 файла: 4 секунды(играет с 0), 2.5 секунды(играет с 3 с) и 5 секунд(играет с 3 с), все файлы 16bit,stereo, 44100.
                                  1. Создаю массив
                                  ExpandedWrap disabled
                                    int SamplesPerSecond = 44100;
                                    int ResultRecordingLength = 7;
                                    short[] resultArray = new short[ResultRecordingLength * SamplesPerSecond];

                                  Получается массив для 7 секундного файла, так?
                                  2. Мне его надо инициализировать?
                                  ExpandedWrap disabled
                                    for(int i=0;i<resultArray.Length;++i)
                                    {
                                      resultArray[i]=0;
                                    }

                                  3. С помощью кода выше, я могу прочитать первый 4 секундный файл. Получаю его данные в двух массивах:
                                  ExpandedWrap disabled
                                    lDataList;
                                    rDataList;

                                  4. Теперь мне надо эти данные записать в resultArray, так?
                                  ExpandedWrap disabled
                                    for(int readIndex=0; ((readIndex<sourceSound.Count)&&(readIndex+sourceSound.Count<resultArray.Length)); ++readIndex)
                                    {
                                      resultArray[readIndex] += sourceSound[readIndex];
                                    }

                                  Это кода для mono файла, а как быть со stereo?
                                  ExpandedWrap disabled
                                      resultArray[readIndex] += lDataList[readIndex];
                                      resultArray[readIndex+1] += rDataList[readIndex];

                                  так?
                                  Поправьте пожалуйста если по другому?

                                  5. Потом также читаю второй файл. Вот тут дальше не знаю, как правильно сделать нормализацию? Вот и думал применить ту формулу...

                                  Цитата Prince @
                                  Откуда такая формула?

                                  Формулу взял вот тут: http://www.vttoth.com/CMS/index.php/technical-notes/68
                                    Цитата rodrigosan @
                                    Только с C# у меня никак не получается разобраться, с чего начать?

                                    С умной книжки по C#.
                                    Цитата rodrigosan @
                                    Как сложить семплы для определенного времени?

                                    Операцией сложения и нормализации (как правило умножения на коэффициент). Ваш КО.
                                    Цитата rodrigosan @
                                    Я так понял сначала нужно прочитать wav файлы в short?

                                    Нужно прочитать заголовок, выудить из него инфу о типе PCM-данных (структура wav гуглится на раз-два) и найти смещение самих данных. Далее можно уже считывать сами PCM-данные. Размер сэмпла не всегда 16 бит, так что "жесткое" использование некорректно.
                                    Цитата rodrigosan @
                                    Это для стерео ?

                                    Для стерео и моно нету практически никакой разницы.
                                    Цитата rodrigosan @
                                    Нашел формулу для двух файлов, Z=A+B−AB, но как ее применить?

                                    Никак не применишь. Формула явно не для твоего случая. Вот тебе формула out_sample[i] = in_sample[0][j] * c1 + in_sample[1][k] * c2; c1, c2 - коэффициенты нормализации. Для случая, если формат PCM идентичен, достаточно такой формулы out_sample[i] = (in_sample[0][i] + in_sample[1][i]) * C. Как считать коэффициент нормализации уже тут написано. Если лень, то можешь взять его равным 0.5. Но тогда уменьшится громкость.

                                    Добавлено
                                    Цитата rodrigosan @
                                    первые 44 байта заголовок, а дальше данные.

                                    Это не так. Точнее не всегда так. После заголовка могут следовать метаданные.

                                    Добавлено
                                    Цитата rodrigosan @
                                    Формулу взял вот тут

                                    Цитата
                                    If we take A and B to have values between 0 and 1, there is actually a simple equation that satisfies all of the above conditions:
                                    .
                                    Там дальше описывается формула для нормализации реальных данных, но мне это формула не нравится: она учитывает только мгновенные значения сэмпла, что чревато искажениями.

                                    Добавлено
                                    Цитата rodrigosan @
                                    Получаю его данные в двух массивах:

                                    Зачем 2 массива?
                                    Цитата rodrigosan @
                                    4. Теперь мне надо эти данные записать в resultArray, так?

                                    Я с трудом понимаю, что ты этим пытаешься сделать. И если resultArray равен по размеру sourceSound это неверно : при сложении двух семплов можетпроизойдет переполнение и на выходе ты получишь не звук, а шум.
                                    Цитата rodrigosan @
                                    а как быть со stereo?

                                    Точно так же. Не надо обрабатывать отдельно каналы, учитывай только, что идет по два сэмпла на один уровень дискретизации.
                                    Сообщение отредактировано: shm -
                                      Цитата
                                      Формулу взял вот тут:

                                      Ерунда. Произведение сигналов - нелинейная операция, привносящая в микс(сумму сигналов) искажения, которых там ни разу быть не должно.
                                        Цитата Prince @
                                        Ерунда.

                                        Не совсем. Он выдрал формулу для случая, когда значения сэмпла в диапазоне от 0 до 1. В общем виде она выгляди так Z = A + B - A*B / 2bits_per_sample. Но соглашусь, что в общем случае звук это испортит хотя бы их тех соображений, что если к одному источнику звука добавить еще один, то результирующий звук должен иметь бОльшую громкость. А большую громкость можно получить только за счет снижения громкости остальных сэмплов, поэтому хороший способ нормализации должен основываться на поиске максимума и нормализации основных значений под него.
                                        Сообщение отредактировано: shm -
                                          Цитата shm @
                                          Цитата Prince @
                                          Ерунда.

                                          Не совсем. Он выдрал формулу для случая, когда значения сэмпла в диапазоне от 0 до 1. В общем виде она выгляди так Z = A + B - A*B / 2bits_per_sample. Но соглашусь, что в общем случае звук это испортит хотя бы их тех соображений, что если к одному источнику звука добавить еще один, то результирующий звук должен иметь бОльшую громкость.

                                          Совсем.
                                          Если просуммировать(микшировать) 2 одинаковых сигнала, на выходе должны получить А+А=2А (усиление громкости)
                                          По формуле того дяди миксом будет называться 2А-A^2, т.е., собсно микс + какой-то левый нелинейный придаток. Насколько я понял его идею, он хотел впихнуть невпихуемое, т.е., например, в динамический диапазон 16 бит впихнуть два 16 битных сигнала без потери громкости составляющих или как-то так.
                                          Если микс не вылазит за 16 бит, громкость(уровень) составляющих и так не изменится. Если же вылазит, необходимо уменьшать уровень составляющих микс сигналов. Как ни крути.
                                          Сообщение отредактировано: Prince -
                                            rodrigosan
                                            Рано вам ещё со звуком работать. Вам бы программировать поучиться.
                                            Сообщ. #16
                                            Цитата rodrigosan @
                                            Получается массив для 7 секундного файла, так?

                                            1. Нет не так, вы же стерео хотели. ДА и внутреннее представление данных для обработки я бы выбрал с плавающей точкой.
                                            2. Нет. Читай учебник про матрицы и массивы.
                                            3. Код в 14 сообщение не правильный. Читайте формат файла. Какой формат данных у отсчёта(сэмпла) в PCM16?
                                            4.1. Нет.
                                            4.2. Нет. Индексы неправильные.
                                            Вам бы на простых задачах с циклами и матрицами потренироваться, с выводом на экран. Так сразу ошибки видны.
                                            И править не буду. Одно дело поймать рыбу другое дело научить ловить рыбу. Такие задачи вы должны решать сами.
                                            5. Качественное микширование звука задача не простая. Обычно звук складывают линейно с некоторыми коэффициентами. Коэффициенты эти не постоянные они меняются с течением времени плавно или резко переходя от одних значений к другим. Коэффициенты подбираются оператором(пользователем) - в музыкальной среде диджеям. Сейчас используют как правило более сложные алгоритмы и автоматически подбирают параметры нормализации.
                                            Для двух файлов можно взять коэффициенты 0.5. Но недостатки такого подхода известны. Если в одном из файлов есть пауза или тишина или за конецом файла
                                            То результат будет очень тихий, что заметно на слух.
                                            И линейно складывать больше 4 файлов как бы не рекомендуется.
                                              Цитата
                                              И линейно складывать больше 4 файлов как бы не рекомендуется

                                              А как можно складывать нелинейно?
                                              Допустим, минусовка содержит 10 треков, что очевидно больше 4-х. Всё, не судьба?

                                              Цитата
                                              Качественное микширование звука задача не простая. Обычно звук складывают линейно с некоторыми коэффициентами. Коэффициенты эти не постоянные они меняются с течением времени плавно или резко переходя от одних значений к другим. Коэффициенты подбираются оператором(пользователем) - в музыкальной среде диджеям. Сейчас используют как правило более сложные алгоритмы и автоматически подбирают параметры нормализации.

                                              Та вы так вообще человека запутаете.
                                                Prince
                                                Наверно слова не правильно подобрал имеется в виду с постоянными коэффициентами. И то это связано с шумами в аналоговой технике. Если у вас есть запись очищенная от шумов, то конечно можно. И тем более не рекомендуется это не значит что нельзя. Просто возможны ухудшения в определенных условия.
                                                  Цитата Pavia @
                                                  1. Нет не так, вы же стерео хотели. ДА и внутреннее представление данных для обработки я бы выбрал с плавающей точкой.

                                                  Почему с плавающей точкой?
                                                  Еще я немного запутался. Как задать размер массива для нового файла? Зная, что новый файл должен быть 7 секунд?
                                                  В 1 пункте я создавал mono да, для стерео получается он в два раза больше должен был быть?
                                                  И сам вопрос размера, я делал как написано тут: http://stackoverflow.com/questions/8375149...file-mp3-or-wav
                                                  ExpandedWrap disabled
                                                    int SamplesPerSecond = 44100;
                                                    int ResultRecordingLength = 7;
                                                    ResultantSound = new short[ResultRecordingLength*SamplesPerSecond];


                                                  Но сейчас думаю, что это не правильно, т.к. размер должен был быть:
                                                  ExpandedWrap disabled
                                                    int bytePerSec = 176400;
                                                    int ResultRecordingLength = 7;
                                                    ResultantSound = new short[ResultRecordingLength*bytePerSec ];

                                                  В 3 пункте, мне не нужно универсальный способ, в моем случае требуется читать файлы только формата: 16bit, 44100, stereo. И судя по данным которые считывает код, все верно.
                                                  С индексами да я наверное ошибся, писал торопился... Я хочу понять саму суть создания wav файлов для моего конкретного случая...
                                                    Цитата rodrigosan @
                                                    Как задать размер массива для нового файла?

                                                    Рекомендую все же почить про PCM. КО намекает, что перемножив длительность (сек), частоту сэмлов (гц), размер сэмпла (байт) и количество каналов мы получим размер данных, который будет занимать PCM-блок искомой длительности.
                                                    Сообщение отредактировано: shm -
                                                      rodrigosan
                                                      Цитата rodrigosan @
                                                      Почему с плавающей точкой?

                                                      Удобнее.
                                                      1. Динамический диапазон шире поэтому переполнения не будет.
                                                      2. Если и будет переполнение, то оно компенсируется округлением.
                                                      3. Определено больше операций следовательно не придётся их заново изобретать.

                                                      Но на самом деле это только для модели или быстрой разработки годится. Проблем это не решает. А для серьёзной для очень серьёзной лучше в целых.

                                                      Цитата rodrigosan @
                                                      Еще я немного запутался. Как задать размер массива для нового файла? Зная, что новый файл должен быть 7 секунд?
                                                      В 1 пункте я создавал mono да, для стерео получается он в два раза больше должен был быть?

                                                      Да.

                                                      Цитата rodrigosan @
                                                      Но сейчас думаю, что это не правильно, т.к. размер должен был быть:

                                                      С чего бы в друг? Чем byte отличается от short? Можно и через байты делать только смысла в этом нет. Надо делать как проще. А не как сложнее.
                                                      В PCM16 данные записаны в short. Зачем возиться с байтами и выравниванием и конвертированием?

                                                      Цитата rodrigosan @
                                                      В 3 пункте, мне не нужно универсальный способ, в моем случае требуется читать файлы только формата: 16bit, 44100, stereo. И судя по данным которые считывает код, все верно.
                                                      С индексами да я наверное ошибся, писал торопился... Я хочу понять саму суть создания wav файлов для моего конкретного случая...

                                                      Суть вы улавливаете. Только у вас много ошибок. Я в таком случае советую не спешить, а делать всё последовательно небольшими шагами. Написали строчку проверили. Написали другую проверили итд.
                                                        Вообщем получилось у меня создать 7 секунд тишины, а потом с нужной мне позиции добавить нужный звук равный 2 сек.
                                                        Потом получилось добавить еще один звук равный 3 сек, так чтобы звуки пересеклись.
                                                        Обработал их потом так:
                                                        ExpandedWrap disabled
                                                          int max = int.MinValue;
                                                                      int min = int.MaxValue;
                                                                      for (int i = 0; i < resultArray.Length; ++i)
                                                                      {
                                                                          max = Math.Max(max, resultArray[i]);
                                                                          min = Math.Min(min, resultArray[i]);
                                                                      }
                                                                      double scale = 65536d / (double)(max - min);
                                                                      double offset = 32767 - (max * scale);
                                                                      for (int i = 0; i < resultArray.Length; ++i)
                                                                      {
                                                                         resultArray[i]= (short)((scale*resultArray[i])+offset);
                                                                      }

                                                        Более-менее нормализация прошла. Над этим еще буду работать, как лучше нормализацию провести.
                                                        На маленьких файлах у меня все прошло отлично. А вот когда захотел создать файл равный 300 сек, то тут во время заполнения массива произошла ошибка OutOfMemory.
                                                        ExpandedWrap disabled
                                                           List<short> tDataList = new List<short>();
                                                           using (BinaryReader br = new BinaryReader(mFileStream))
                                                                      {
                                                                          try
                                                                          {
                                                                              Header.riffID = br.ReadBytes(4);
                                                                              Header.size = br.ReadUInt32();
                                                                              Header.wavID = br.ReadBytes(4);
                                                                              Header.fmtID = br.ReadBytes(4);
                                                                              Header.fmtSize = br.ReadUInt32();
                                                                              Header.format = br.ReadUInt16();
                                                                              Header.channels = br.ReadUInt16();
                                                                              Header.sampleRate = br.ReadUInt32();
                                                                              Header.bytePerSec = br.ReadUInt32();
                                                                              Header.blockSize = br.ReadUInt16();
                                                                              Header.bit = br.ReadUInt16();
                                                                              Header.dataID = br.ReadBytes(4);
                                                                              Header.dataSize = br.ReadUInt32();
                                                           
                                                                              for (int i = 0; i < Header.dataSize / Header.blockSize; i++)
                                                                              {
                                                           
                                                                                  tDataList.Add((short)br.ReadUInt16());
                                                                                  tDataList.Add((short)br.ReadUInt16());
                                                                              }
                                                                          }

                                                        Ошибка OutOfMemory возникает в строке tDataList.Add((short)br.ReadUInt16());
                                                        Забыл еще сказать, что пробую все это на WindowsPhone. В принципе вначале это было не важно, т.к. хотел разобраться с основами.
                                                        Что теперь остается? отказаться от short массива? И работать только с BinaryReader ?
                                                          Про нормализацию: Как правильно найти коэффициент нормализации?
                                                          перечитал заново всю тему и нашел только, что предлагалось делить на кол-во одновременно играющих звуков?
                                                          т.е. если два звука одновременно играют, то (sample1 +sample2)*0.5 так? в итоге, мне это только уменьшило громкость.
                                                            Цитата rodrigosan @
                                                            т.е. если два звука одновременно играют, то (sample1 +sample2)*0.5 так?

                                                            Это самый тупой вариант. Ищешь max(sample1[i] + sample2[i]), находишь коэффициент нормализации (2bits_per_sample - 1) / max. Потом домнажаешь все суммы на этот коэффициент. Подразумевается, что промежуточные манипуляции должны производиться в ячейках бОльшей разрядности, чем sample1[i], в силу очевидных причин.
                                                            Сообщение отредактировано: shm -
                                                              rodrigosan
                                                              Раз в 20 мс параметр надо подбирать заново. Чаще не стоит, реже может быть. Надо смотреть статьи в звуке я не очень.
                                                              Рассмотрим варианты смешивания
                                                              1)Samle1+Samle2
                                                              2)0.5*(Samle1+Samle2)
                                                              3)Max(Samle1,Samle2)
                                                              4)Amp1(freanch)+Amp1(freanch2)

                                                              1) Разговор двух человек. Хорошо работает если говорит один второй молчит. Или первый молчит второй говорит громкость не падает.
                                                              Если оба говорят одновременно имеем переполнение. Решение коэффициент ставить 0.5
                                                              2) Разговор двух человек. Плохо работает так как будет в 2 раза тише.
                                                              Как вариант если второй не говорит то коэффициент ставить 1.
                                                              3) Отсутствую проблемы с переполнением в тоже время снижает динамический диапазон. Но на двух файлах должно работать хорошо.

                                                              1-3 пункты имеют также недостатки. Они не учитывают ещё 2 вещи. Это наличие постоянной составляющей. Её надо будет предварительно убирать. Не учитывают фазы звуков.
                                                              Если у нас два одинаковых звука в противофазе, то мы получим тишину. На самом деле при любом таком сложение будет ослабевание звука.
                                                              А если у нас несколько файлов то звуки будут стремиться к голосовому шуму.
                                                              Решение использовать сложение амплитуд в частотной области т.е формула 4) при этом фаза звуков выравниваются.
                                                              Недостаток 4) очевиден страдает фазы звуков. А значит ударные звуки будут искажаться. Как следствие вычисляют такие звуки и их обработку ведут специальным образом.

                                                              И да я молчу про то, что по мимо удаления постоянной составляющей надо ещё и от шумов почистить звуки.
                                                              А да забыл сказать что изменение коэффициентов должно идти плавно иначе на стыке окон будет не стыковка фазы и будут появляться щелчки. Либо второй вариант вести обработку с перекрытием окон.
                                                              Сообщение отредактировано: Pavia -
                                                                Цитата Pavia @
                                                                Раз в 20 мс параметр надо подбирать заново. Чаще не стоит, реже может быть. Надо смотреть статьи в звуке я не очень.

                                                                Однозначно реже и это имеет смысл, если требуется манипуляции со звуком со входа в реальном времени. Звуковые редакторы в плане нормализации, по крайней мере по моим ощущениям, работают именно как я написал.
                                                                Сообщение отредактировано: shm -
                                                                  Цитата rodrigosan @
                                                                  Про нормализацию: Как правильно найти коэффициент нормализации?
                                                                  перечитал заново всю тему и нашел только, что предлагалось делить на кол-во одновременно играющих звуков?
                                                                  т.е. если два звука одновременно играют, то (sample1 +sample2)*0.5 так? в итоге, мне это только уменьшило громкость.

                                                                  Так и должно быть. Вникните:(A+B)/2. Если A или B равны 0 - результат равен A/2 или B/2, уровень составляющих уменьшился.
                                                                  Если на 2 не делить, то сумма может выйти за допустимый диапазон значений(он ограничен по условию задачи). (A+B)/2 - для ленивых, а по-человечески компромисным вариантом будет сложить и нормализовать(привести уровень микса к некоему заданному уровню, "норме").
                                                                  Тот человек, чью формулу вы приводили, пытался найти бескомпромисный вариант, вероятно существующий в -цатом измерении. A+B-AB. При A=0, микс=B. При B=0, микс=A. Красотища! Уровень А и В не меняется! При ненулевых A и В получаем нечто, но не микс. Например, при "смешивании" таким способом синусоидальных сигналов с частотами 5 и 1 кГц помимо суммы сигналов, на выходе получим "левые" сигналы в спектре, с частотами 4 и 6 кГц.

                                                                  Умножать на 0.5(на 1/n) не нужно, раз уж вы хотите вникнуть. 0.5 - для ленивых и больше про 0.5 говорить нет смысла.

                                                                  Приведу вам иллюстрацию, которой я пользовался в другой теме, для того, чтобы наглядно представить то, что вы делаете со звуком.
                                                                  У вас есть две литровых банки с некими растворами. В одной литр(полная банка), в другой 0.5 литра. Вам их нужно смешать. Для хранения готовой смеси у вас тоже литровая банка. Очевидно, что в литровую банку 1.5 литра никак не влезут. Теперь представьте, что у вас есть 3-х литровая банка для смешивания(вы в ней смешиваете что-то, потом моете и снова что-то смешиваете, такая себе "рабочая банка"). Вы смешали, получили 1.5 литра смеси. Теперь вам нужно вычислить "коэффициент нормализации" для того, чтобы узнать, какую часть смеси нужно взять, чтобы она "нормально" влезла в литровую банку и не переливалась через край. 1 литр(объём миксовой тары) делим на 1.5 литра (объём микса), получаем 0.666666. Берём 0.66666 от нашего микса (1 литр) и выливаем в литровую банку. Готово.
                                                                  Аналогия не абсолютно точная, так как у нас осталась лишняя смесь, а в математике у нас не осталось лишних чисел, мы их просто пропорционально уменьшили. Но очень и очень наглядная. Можно представить, что 0.6666 - это коэффициент "ужатия" смеси, насколько нужно сжать её, чтобы она влезла в тару. Если взять вместо 1 и 0.5 значения 0.1 и 0.5, получим объем смеси 0.6 литра. Допустим, большего количества ингридиентов у нас нет, взять негде, а нам хочется, чтобы был 1 литр. Значит, нам нужно как-то "расшририть" смесь, в 1/0.6=1.666666 раз. В реальности мы этого сделать не можем, в мире чисел запросто.
                                                                  3-х литровая банка в этой аналогии - число большей разрядности, нежели исходные данные и конечный результат, целочисленное или вещественное, о чём скажу дальше.

                                                                  Возвращаясь к нормализации, коэффициент зависит от уровня, к которому вы хотите привести микс(от уровня нормализации, "объёма тары").
                                                                  Если работаете с целочисленными значениями, считайте, как shm говорит(только 1 отнимать не нужно,или нужно? :scratch: ). Так вы приводите микс к пиковому уровню 0 дБ, максимально возможному для разрешения bits_per_sample, к "1 литру".

                                                                  А вообще, вычисления удобно проводить над вещественными, и лучше приведенными к 1.0, значениями. Тогда вас не будет волновать битовое разрешение аудио и переливание через крайпереполнение в промежуточных вычислениях. На конечном этапе возвращаетесь к целым значениям.

                                                                  Т.е., делите целочисленные значения на максимальное абсолютное значение семпла для данного битового разрешения(32768 для 16 бит). Получаете значения в диапазоне -1.0 .. +1.0, и дальше не зависите от исходного формата семплов(допустим, файлы имеют разный формат). Дальше смешиваете треки:
                                                                  mix= G(1)*s(1)+G(2)*s(2)+...+G(n)*s(n), где s - аудиоданные трека, а G(Gain) - коэффициент усиления(или ослабления) трека("пропорция смеси"). Лирическое отступление: обычно требуется смешивать сигналы в разных пропорциях, что-то должно звучать тише, что-то громче. Для наглядности, регуляторы в микшере винды - это тоже регуляторы Gain.
                                                                  Допустим, вы приняли все G(i)=1.0, т.е., смешали треки как есть, без изменения их уровня, без балансировки.
                                                                  Дальше нормализуете микс(приводите максимальный пиковый уровень микса) к какому-то заданному уровню:
                                                                  Уровень измеряется в дБ и за 0дБ пикового уровня цифрового звука принимают значение, соответствующе максимально возможному значению семпла. Поскольку вы вначале поделили семплы на это самое значение(поделили на 32768, привели к 1.0), 1.0("1 литр", помните?) в мире нормализованных вещественных значений и будет соответствовать максимально возможному значению семпла, или 0дБ.
                                                                  Скажем, вы прошерстили микс и нашли, что максимальное значение семпла равно 0.7654321. Или ,в дБ: 20*log(0.7654321/1.0)=-2.32 дБ. А вы хотите максимально возможные 0 дБ (1.0) на выходе получить. Очевидно, "поправочный" коэффициент будет 1.0/0.7654321=1.3.
                                                                  Или вы задаётесь уровнем -10 дБ. 10^(-10/20)*1.0 = 0.316. В этом случае, коэффициент 0.316/0.7654321=0.41. Т.е., ваш микс "громче", чем вам нужно, и вам нужно сделать его "тише".
                                                                  Затем возвращаетесь к целочисленным зачениям, умножая на 327678 32767 с округлением. :scratch:

                                                                  На всякий пожарный, нормализация микса не является обязательной, т.е., "вообще_обязательной_и_без_неё_вообще_нельзя". Нормализация необходима, если микс "вылазит" за максимальный возможный уровень для данного битового разрешения, потому что без нормализации получим искажения. А вообще - это дело добровольное. И помимо нормализации существуют и другие методы и средства обработки(компрессоры, лимитеры, экспандеры и пр.)

                                                                  То, о чём говорит Pavia, по поводу периодического изменения коэффициента - это уже динамическая обработка сигнала, и высокие материи, называется компрессией. Хотя и нормализацией тоже иногда обзывают, но обычно нормализацией называют то, что описано выше.
                                                                  Сообщение отредактировано: Prince -
                                                                    Цитата Prince @
                                                                    Приведу вам иллюстрацию, которой я пользовался в другой теме, для того, чтобы наглядно представить то, что вы делаете со звуком.

                                                                    Спасибо большое! Все на пальцах объяснили, теперь стало понятно. С нормализацией все получилось, полученный результат меня полностью устроил:)
                                                                    А можно еще вопрос про pitch ? Я вот еще прочитал что для одного файла можно изменить pitch путем изменения частоты в заголовке. А как быть если мне нужно сложить два wav файла, при этом у одного из них нужно чтобы был изменен pitch? Если я изменю заголовок, то pitch изменится для всего файла. Есть ли способ изменяя Data добиться изменения pitch в wav файле?
                                                                      Цитата rodrigosan @
                                                                      pitch

                                                                      Это че за терминология?
                                                                        Цитата shm @
                                                                        Это че за терминология?

                                                                        Не знаю как точно перевести это свойство, наверное: Высота звука.
                                                                        К примеру есть класс SoundEffect. Это стандартный класс из Microsoft.Xna.Framework.Audio.
                                                                        У объекта этого класса есть метод
                                                                        ExpandedWrap disabled
                                                                          Play(float volume, float pitch, float pan);

                                                                        pitch изменяется от -1 до 1. При 0 звук воспроизводится нормально, при 1 ускоренно, при -1 замедленно.

                                                                        из msdn:
                                                                        Цитата
                                                                        Pitch adjustment, ranging from -1.0f (down one octave) to 1.0f (up one octave). 0.0f is unity (normal) pitch.

                                                                        Я хочу сделать примерно тоже самое со своими некоторыми wav файлами, что делает это свойство в SoundEffect.
                                                                        Сообщение отредактировано: rodrigosan -
                                                                          Prince
                                                                          Как много букв. Нормализация это приведение диапазона значений (в ЦОС чисел) к заданному диапазону. Простая школьная задачка на дроби и пропорции.
                                                                          Есть несколько способов о них ниже.

                                                                          Небольшое отступление от темы.
                                                                          А вот у rodrigosan видимо путаница в терминах. Надо сказать, что при микширование выполняется усиление или ослабление сигнала. А также и нормализация. При этом первое и второе может выполняться одновременно.
                                                                          В моем предыдущем сообщение, расписывалось только микширование, а о нормализации я вообще не говорил. Как заметил Prince она не является обязательной. Так что как видно разных схем микширования много.
                                                                          Компрессия это другое, это либо:
                                                                          - сжатие динамического диапазона;
                                                                          - сжатие частотного диапазона;
                                                                          - сжатие временного разрешения.

                                                                          Вот сжатие динамического диапазона можно отнести к нормализации.
                                                                          Вернемся к теме.
                                                                          Нормализация для положительно определенных чисел выглядит так:
                                                                          OutValue=(InValue-InMin)/(InMax-InMin) - приводим к диапазону 0..1
                                                                          OutValue=(InValue-InMin)/(InMax-InMin)*(OutMax-OutMin)+OutMin - приводим к выходному
                                                                          Так как в звуке по большей части принят не только положительно определенный, но отрицательные числа, то нормализацию можно сделать так.
                                                                          OutValue=InValue/InMax*OutMax, где InMax выбирается по абсолютной величине :scratch: т.е из -1,3 и +1,1 выбирается +1,3.
                                                                          При такой формуле сохраняется положения нуля.

                                                                          Выбор InMax, OutMax достаточно произвольная операция.
                                                                          OutMax обычно берётся как целочисленные значения на максимальное абсолютное значение семпла для данного битового разрешения(327687 для 16 бит).
                                                                          Это для вывода в файл, а вот в промежуточных расчётах скорее к +1,0 .

                                                                          Цитата Prince @
                                                                          То, о чём говорит Pavia, по поводу периодического изменения коэффициента

                                                                          Не нравится мне как тут звучит слово периодическое. Скорее динамическое и лучше если оно будет непрерывным.
                                                                          Сообщение отредактировано: Pavia -
                                                                            Цитата rodrigosan @
                                                                            со своими некоторыми wav файлами

                                                                            меняешь samplerate в заголовке и все.
                                                                              Цитата shm @
                                                                              меняешь samplerate в заголовке и все.

                                                                              я же писал чуть выше это...
                                                                              Ну ведь data не изменится у этого файла?
                                                                              Мне нужно сложить два файла. Один обычный + второй с измененным pitch.
                                                                              Сообщение отредактировано: rodrigosan -
                                                                                Цитата rodrigosan @
                                                                                pitch

                                                                                Не используй левые термины, даже если их придумывает M$.
                                                                                В самом простом случае достаточно дублировать или (наоборот удалять) сэмплы с шагом n, хотя это и не совсем корректно. Может Prince подскажет простой и корректный вариант.
                                                                                Ну для примера:
                                                                                вот есть фрагмент данных с SampleRate = n
                                                                                3 1 4 1 5 9 2 6 5
                                                                                вот так можно уменьшить SampleRate в 2 раза
                                                                                3 4 5 2 5
                                                                                ну или увеличить в два раза:
                                                                                3 3 1 1 4 4 1 1 5 5 9 9 2 2 6 6 5 5
                                                                                хотя более корректно с использованием интерполяции:
                                                                                2 2 7 4 5
                                                                                3 2 1 2 4 2 1 3 5 7 9 5 2 4 6 5 5 5

                                                                                с такой "интерполяцией" получится фигня.
                                                                                Сообщение отредактировано: shm -
                                                                                  Цитата rodrigosan @
                                                                                  pitch изменяется от -1 до 1. При 0 звук воспроизводится нормально, при 1 ускоренно, при -1 замедленно.

                                                                                  http://en.wikipedia.org/wiki/Pitch_(music)
                                                                                  Судя по описанию это скорость звука качественно воспринимаемая человеком переложенная на количественное значение.
                                                                                  Качественная означает что человек может сравнить два звука и сказать быстрее или медленнее. На основе такого вот сравнения построили зависимость для разных скоростей. И оказалось что: в следствии особенности восприятия звука человеком реальное увеличение скорости расходиться с ощущаемым. Причем чем расхождение не линейное. Чем больше разница тем больше расхождение.

                                                                                  Для изменения скорости в файле вам надо изменить дискретность. Или другими словами передискретизация.
                                                                                  "Алгоритм" передискретизации можно найти в книге "А.Б.Сергиенко_Цифровая обработка сигналов".

                                                                                  Для shm
                                                                                  Добавлено
                                                                                  Цитата shm @
                                                                                  В самом простом случае достаточно дублировать сэмплы с шагом n, хотя это и не совсем корректно. Может Prince подскажет простой и корректный вариант.

                                                                                  Никто не знает как человек воспринимает звук. А посему о никто не знает корректный вариант. Так что ваш вариант ни чуть не хуже других. Но если проводить сравнения возможно найдутся варианты лучше.
                                                                                  Более правильным считается следующий алгоритм, но экспериментальных сравнений я не видел. Последовательность добавляется нулями потом сигнал фильтруется(интерполируется). А если говорить о высших материях, то там ещё советуют подмешивать псевдошумовые последовательности.
                                                                                  Сообщение отредактировано: Pavia -
                                                                                    Цитата
                                                                                    Как много букв. Нормализация это приведение диапазона значений (в ЦОС чисел) к заданному диапазону. Простая школьная задачка на дроби и пропорции.

                                                                                    Верно.
                                                                                    Цитата
                                                                                    Вот сжатие динамического диапазона можно отнести к нормализации.

                                                                                    Неверно. Нормализация не затрагивает динамический диапазон и тем сильно отличается от компрессии. Нормализация - это "мы выставляем регулятор громкости в нужное нам положение и наслаждаемся", а компрессия - "мы постоянно крутим регулятор громкости, на тихих звуках крутим вправо, на громких - влево". После нормализации мы имеем фактически оригинальный звук. После компрессии уже нет.
                                                                                    Цитата
                                                                                    Не нравится мне как тут звучит слово периодическое. Скорее динамическое и лучше если оно будет непрерывным.

                                                                                    Ну тут можно было бы подумать, что динамическая обработка - это типа обработка в реалтайме, хотя динамическая обработка связана с изменением динамического диапазона.
                                                                                    Да, непрерывное звучит лучше, но не суть. Я всего лишь хотел подсказать человеку, что "оно ему сейчас не надо".
                                                                                    Сообщение отредактировано: Prince -
                                                                                      Цитата shm
                                                                                      В самом простом случае достаточно дублировать или (наоборот удалять) сэмплы с шагом n, хотя это и не совсем корректно.

                                                                                      В первом случае после дублирования прогонять через ФНЧ, а во втором случае перед удалением прогонять через ФНЧ. Когда-то я такую штуку делал.
                                                                                      Но с целым n неинтересно, n=2 уже сдвигает высоту аж на октаву.
                                                                                      а вот если нужно сдвинуть на полтона, понадобится передискретизация, например, от 48000 Гц к 50854 Гц, как тут быть? Двойная передискретизация *m/n с целыми m и n не прокатит, очень уж большая частота передискретизации выйдет. :scratch:
                                                                                      Сообщение отредактировано: Prince -
                                                                                        Цитата Prince @
                                                                                        только 1 отнимать не нужно,или нужно?

                                                                                        конечно нужно
                                                                                        допустим имеем для 8 бит
                                                                                        max(a[i] + b[i]) = max(255 + 1) = 256
                                                                                        c = 256 / 256 = 1;
                                                                                        out[i_max] = 256 * 1 = 256 -> 0

                                                                                        Добавлено
                                                                                        Цитата Prince @
                                                                                        дублирования прогонять через ФНЧ

                                                                                        А просто интерполяция как я показал в примере не прокатит?

                                                                                        Добавлено
                                                                                        может поэкспериментирую на досуге

                                                                                        Добавлено
                                                                                        Цитата Prince @
                                                                                        от 48000 Гц к 50854 Гц, как тут быть?

                                                                                        я бы сделал как-то так (идея стырена из алгоритма Брезенхема):
                                                                                        ExpandedWrap disabled
                                                                                          int sr1 = 48000, sr2 = 50854;
                                                                                          int delta = sr2 - sr1;
                                                                                          int err = sr1;
                                                                                          for(int out_idx = 0, in_idx = 0; in_idx < len;  in_idx++)
                                                                                          {
                                                                                              out[out_idx++] = in[in_idx];
                                                                                              err -= delta;
                                                                                              if(err <= 0)
                                                                                              {
                                                                                                  out[out_idx++] = in[in_idx];
                                                                                                  err += sr1;
                                                                                              }
                                                                                          }
                                                                                        Сообщение отредактировано: shm -
                                                                                          Цитата shm @
                                                                                          Добавлено
                                                                                          Цитата Prince @
                                                                                          дублирования прогонять через ФНЧ

                                                                                          А просто интерполяция как я показал в примере не прокатит?

                                                                                          Добавлено
                                                                                          может поэкспериментирую на досуге

                                                                                          Да прокатит, почему нет. Результат будет зависеть от способа интерполяции. Дублирование - тоже ведь интерполяция.
                                                                                          Если обработать фильтром, можно нулевыми значениями забить промежуточные значения, фильтр всё "интерполирует" в итоге.
                                                                                            Цитата Prince @
                                                                                            Да прокатит, почему нет.

                                                                                            Сейчас попробовал: не прокатит. Появился шум. А вот тупое дублирование дает неплохой результат.

                                                                                            Добавлено
                                                                                            Попробовал мой алгоритм - вполне прокатывает.
                                                                                            Цитата shm @
                                                                                            Сейчас попробовал: не прокатит. Появился шум.

                                                                                            Подозреваю, что для звука не пригодно линейное интерполирование.

                                                                                            Добавлено
                                                                                            Почитал матчать, таки корректное интерполирование весьма нетривиальная задача. Если рассматривать корректные решения, то всех проще таки использовать ФНЧ.
                                                                                            Сообщение отредактировано: shm -
                                                                                            1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                                                            0 пользователей:


                                                                                            Рейтинг@Mail.ru
                                                                                            [ Script execution time: 0,1571 ]   [ 15 queries used ]   [ Generated: 19.05.24, 20:05 GMT ]