На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Запись потока с линейного входа , Разделить поток линейного входа на 2 разных в первом только левое моно, а во втором только правое моно
    Здравствуйте...
    Есть, к примеру, телефон, я его подключаю к звуковой карте на линейный вход... мне нужно входящий стерео поток разделить на 2 моно, то есть в первом будет только то что было на левом канале, а во втором только то, что на правом канале... и записывать эти потоки в 2 разных файла. Я почитал bass.dll, посмотрел примеры, но так и не разобрался....
    Помогите пожалуйста разобраться...
    Заранее спасибо!
      Цитата sandist @
      но так и не разобрался....

      Необходимо при открытии устройства указать, что будут два канала:
      ExpandedWrap disabled
        //Создаем заголовок для открытия устройства вывода
            WaveFormat.wFormatTag := WAVE_FORMAT_PCM;
            WaveFormat.nChannels := 1; //Выбор 1 канал моно
        ......
            WaveOut := New(PHWaveOut);
        //Делаем попытку открыть устройство
        //Возможно ИС при занятом устройстве
        //придется перехватывать
            Err := WaveOutOpen(WaveOut, 0, @WaveFormat,
             Handle, 0, CALLBACK_WINDOW);
      Разумеется, сначала необходимо настроить микшер на подключение для захвата линейного входа. :D
        Цитата
        Я почитал bass.dll, посмотрел примеры, но так и не разобрался....
        Помогите пожалуйста разобраться...

        Цитата

        WaveOutOpen
        для захвата

        Медвед, что это было? :-?

        Добавлено
        Цитата
        и записывать эти потоки в 2 разных файла. Я почитал bass.dll, посмотрел примеры, но так и не разобрался....
        Помогите пожалуйста разобраться...

        Разобраться с чем конкретно? Что вызывает трудность?
        Сообщение отредактировано: Prince -
          Цитата Prince @
          Медвед, что это было? :-?

          Комментарий к коду читай. Непонятно? Тогда расшифрую: в коде показано, где формировать количество каналов. Тебе что непонятно то? :D
            Мне непонятно, как человек, не разобравшийся в примерах из справки к басс, сможет из комментариев к вырванному из другой оперы кусочку кода, совершенно неинформативному в контексте поставленных вопросов, понять, как "входящий стерео поток разделить на 2 моно, то есть в первом будет только то что было на левом канале, а во втором только то, что на правом канале... и записывать эти потоки в 2 разных файла". Вот непонятно мне. :-?
              Цитата Prince @
              Мне непонятно

              Т.е. к тому, как сделать так, чтобы был захват ДВУХ каналов у тебя вопросов в контексте моего ответа нет, так? Может подождем автора, убедимся, что он осознал, КАК сделать захват двух каналов при помощи формирования определенной структуры и пойдем далее? Например, отслеживая по флагу чет-нечет и запихивая пришедшие буферы в разные потоки. Но для начала настроить микшер. Или это тебе тоже непонятно? :D
              Цитата Prince @
              Вот непонятно мне. :-?

              Мир даже не заметил твоей тревоги.... Тебе это странно, мне....как то не очень. И это тоже странно? :D

              Добавлено
              Цитата Prince @
              не разобравшийся в примерах из справки к басс

              Кстати, Prince, я вот ни разу не разбирался с этой длл. Но тем не менее не испытываю никаких напряжений в работе со звуком. Тоже странно? :D
                Цитата
                Т.е. к тому, как сделать так, чтобы был захват ДВУХ каналов у тебя вопросов в контексте моего ответа нет, так?

                А вот и не угадал. Есть. Каким боком WaveOutOpen относится к захвату хоть скольких-нибудь каналов?
                Цитата
                Может подождем автора, убедимся, что он осознал, КАК сделать захват двух каналов при помощи формирования определенной структуры и пойдем далее?

                Да подождём, конечно.
                  Цитата Prince @
                  Каким боком WaveOutOpen относится к захвату хоть скольких-нибудь каналов?

                  Никаким. Так же как и WaveInOpen. И? :D
                    Цитата
                    Никаким. Так же как и WaveInOpen

                    Это как. Почему WaveInOpen никаким?
                      Цитата Prince @
                      Почему WaveInOpen никаким?

                      Т.е. с WaveOutOpen ты согласен? :D
                        Цитата
                        Т.е. с WaveOutOpen ты согласен?

                        С тем, что ты сморозил чепуху, с этим WaveOutOpen, конечно, согласен.
                        Сообщение отредактировано: Prince -
                          Спасибо что откликнулись!
                          Я далек от программирования звука, а так с лету понять видимо мозгов мало 😊
                          Если можно дайте мне хоть направление, куда копать, функцию или компонент...
                          Поток данных идет от телефона, на линейный вход, я понял как записывать этот поток, в файле он идет как моно... А как записывать только один канал, ну или вообще накладывать какие-либо фильтры или эффекты на сам поток, не понял
                          Например мне нужно чтобы это стереопоток разбивался, записывался в разные файлы, при этом чтобы он соазу не выводился на выход, а была возможность какой-то из разбитых ранее потоков отдельно в случае необходимости выводить на выходе...
                          Я знаю что надо, но обсалютно не имеею представления с какого конца подойти к этой проблеме...
                          Помогите пожалуйста!!!!!!!!!!
                            Цитата Prince @
                            С тем, что ты сморозил чепуху, с этим WaveOutOpen, конечно, согласен

                            Я пожалуй соглашусь с тем, что ты не разобравшись, что я хотел показать, начал гнать пургу. Это так на тебя похоже, и перед твоими "доводами" блекнет любая "чепуха". :D
                            Цитата sandist @
                            Поток данных идет от телефона, на линейный вход

                            Он идет стерео или моно? Или моно но по двум проводам? Это принципиально, т.к. из моно ты стерео не получишь. Максимум - два одинаковых канала. :D Это раз.
                            Цитата sandist @
                            А как записывать только один канал

                            1. Сначала формируешь структуру и открываешь устройство. Что за структура и как ее формировать для открытия как одного так и двух каналов, я показал. Правда "светочи" вцепились в вывод, "аргументируя" необходимостью ввода, но сознательно упуская одну деталь - структура одинакова как для ввода, так и для вывода. По крайней мере в части количества каналов.
                            2. Далее ты подготавливаешь "карусель" из буферов размером 1024 байт и фиксируешь их в очереди драйвера.
                            3. Запускаешь открытое устройство на работу и "карусель" начнет тебе выдавать данные. Твоя задача - корректно данные из буфера принять и слить в поток. Если необходимо писать разные каналы раздельно, то что мешает четные буферы сливать в один поток, а нечетные в другой?
                            Совсем подробно все это разжевано здесь. Но повторю, чтобы у тебя был захват необходимого устройства (микрофона/линейного входа) необходимо сначала настроить подсистему микширования, активировав необходимую линию. :D
                            Сообщение отредактировано: medved_68 -
                              Стерео поток на вход идет... А можно сделать так, чтобы со входа звук сразу не шел выход... А если будет нужно пустить на выход один из этих потоков?

                              Добавлено
                              Если можно дай пожалуйста более конкретный пример... Оч большая просьба

                              Добавлено
                              Да ты прав! По двум проводам моно

                              Добавлено
                              А в чем разница? Задача стоит так, идет с 2 микрофонов моно, подаются на вход и выходит стерео... А про телефон я сказал потому что дома испытываю результат на стерео музыке, считал что это равнозначно
                                Цитата sandist @
                                Если можно дай пожалуйста более конкретный пример... Оч большая просьба

                                Мыло в приват - сброшу пример работы с микрофоном и пример настройки микшера на линейный вход на Д7. Как собрать необходимое тебе из двух примеров, добавив раздельную запись потоков на винт - не вижу никаких проблем. :D

                                Добавлено
                                Цитата sandist @
                                Задача стоит так, идет с 2 микрофонов моно, подаются на вход и выходит стерео...

                                Нет проблем. :D
                                  Цитата
                                  Например мне нужно чтобы это стереопоток разбивался, записывался в разные файлы

                                  Прикреплённый файлПрикреплённый файлКопия_RecordTest.rar (3.54 Кбайт, скачиваний: 405)
                                  За основу взят пример из Bass. Захват аудио производится в формате 44100 стерео 16 бит, а на диск пишется сразу 3 файла: стерео, и отдельно левый/правый каналы. Файлы моно имеют в имени приставку L/R.

                                  Добавлено
                                  Цитата
                                  при этом чтобы он соазу не выводился на выход, а была возможность какой-то из разбитых ранее потоков отдельно в случае необходимости выводить на выходе...

                                  Переведите.
                                  :unsure:
                                  Сообщение отредактировано: Prince -
                                    Цитата
                                    Я пожалуй соглашусь с тем, что ты не разобравшись, что я хотел показать, начал гнать пургу.

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

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

                                        Я же тебе говорю - микшер. Погаси в микшере выходной канал и ты ничего в наушниках не услышишь. Аналогично и с выбором входа для звука. :D
                                        Цитата Prince @
                                        и как обычно, уперто твердишь

                                        Ну если светочи непонятливые то как же не твердить то? :-? Ведь белое не станет черным, как бы этого "светочам" не хотелось... :D
                                        Цитата Prince @
                                        просто тебя неправильно поняли. :rolleyes:

                                        Уже теплее, продолжай. :rolleyes: Я зачту слив. ;)
                                          Цитата
                                          Я зачту слив.

                                          Зачти его себе, я тебе его уже зачёл на прошлой странице. :rolleyes:

                                          Добавлено
                                          Цитата
                                          Попробую перевести... я подключаю телефон, где играет стерео, на линейный вход, на той же звуковухе подключаю наушники на линейный выход и слышу музыку...а нужно чтобы ее по умолчанию слышно не было

                                          Выключить в микшере прослушивание линии линейного входа.
                                          Цитата
                                          а было слышно только то, что я сам решу выводить... ну к примеру один из входных потоков...

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

                                          Выключить в микшере запись с линии стерео-выхода или выключить в микшере прослушивание линии линейного входа. Я через форум не могу поковыряться в настройках вашего микшера, а там могут быть варианты.
                                          Сообщение отредактировано: Prince -
                                            Спасибо большое!!! разобрался... но чувствую еще этих вопросов много будет :)
                                              Ошибку допустил в function RecordingCallback:
                                              ExpandedWrap disabled
                                                Form1.WaveStreamL.Write(buffer_L^, length div 2);
                                                  Form1.WaveStreamR.Write(buffer_L^, length div 2);

                                              Во второй строчке должен быть buffer_R^
                                              В TForm1.FormClose добавить
                                              ExpandedWrap disabled
                                                  if BASS_ChannelIsActive(rchan) <> 0 then
                                                  brecord.Click;

                                              иначе, если закрыть окно во время записи, ресурсы не особождаются корректно.
                                              Обновил архив.
                                              Сообщение отредактировано: Prince -
                                                Подскажите пожалуйста еще... насчет того как проигрывать через bass.dll много чего написано, а вот с записью куда скуднее..
                                                Вы подсказали мне как разделить поток и записывать их в файлы.. а как разбить поток на 2, так, чтобы к ним можно было применять эффекты, ну вернее громкость, эквалайзер. Например я записываю звук, а он от источника очень громкий... нужно эквалайзером уменьшить
                                                  Цитата
                                                  Вы подсказали мне как разделить поток и записывать их в файлы.. а как разбить поток на 2

                                                  Вопрос бессмысленный. Разбить, разделить - масло масляное.
                                                  У вас есть кусок памяти(буфер, массив, обзовите как угодно), в котором отсчёты каналов располагаются так:

                                                  Буфер LRLRLRLR...LR

                                                  Каждый отсчёт - 16 бит(2 байтовое число со знаком). Читайте нужные вам отсчёты и обрабатывайте как вам угодно.
                                                  В примере, для того, чтобы записывать в файлы отдельно левый/правый каналы, выделяются дополнительно 2 буфера, куда раскидываются отсчёты из стерео буфера.

                                                  Буфер_L LLLL...L


                                                  Буфер_R RRRR...R

                                                  Потом все три буфера сливаются на диск, в разные файлы.

                                                  Цитата
                                                  Например я записываю звук, а он от источника очень громкий...

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

                                                  Допустим, применили. А дальше?
                                                  Сообщение отредактировано: Prince -
                                                    Как реализовано в примере я понял, но по условию у меня может быть с левого источника громкий звук, а с правого тихий, мне нужно уменьшить к примеру левый... то есть подается стерео звук, но на левом канале нужно уменьшить, на источнике покрутить не вариант, в микшере как я уменьшу именно для левого?
                                                    А нельзя получить данные, их преобразовать и уже потом записывать?
                                                    Времени совсем мало, если можно конкретный пример...
                                                    Спасибо
                                                      Цитата sandist @
                                                      в микшере как я уменьшу именно для левого?

                                                      Баланс при воспроизведении не прокатит?
                                                        ExpandedWrap disabled
                                                            for i:=0 to length div 4-1 do
                                                            Begin
                                                           psample^:=round(psample^*level_L);
                                                            psample_L^:=psample^;
                                                            inc(psample);
                                                            inc(psample_L);
                                                            psample^:=round(psample^*level_R);
                                                            psample_R^:=psample^;
                                                            inc(psample);
                                                            inc(psample_R);
                                                            end;


                                                        level_L/R - коэффициенты, от 0(полная тишина) до 1.0(уровень сигнала не меняется). Если необходимо увеличить уровень, т.е., level_L/R больше 1.0, придётся ввести проверку на переполнение.

                                                        Можно вынести манипуляции с сепмплами в DSP секцию, но раз времени мало, пусть будет так.
                                                        Сообщение отредактировано: Prince -
                                                          Спасибо большое! Еще если можно помогите воспроизвести выбраный канал... вот пробую так, но у меня звук прерывается
                                                          function stream(handle: HSTREAM; buffer: Pointer; length: DWORD; user: DWORD): Cardinal; stdcall;
                                                          var
                                                          c : integer;
                                                          begin
                                                          {c := BASS_ChannelGetData(rchanL, 0, 255);
                                                          if (c > (2 * (0 + 1764))) then
                                                          BASS_ChannelGetData(rchanL, 0, c);}
                                                          c := BASS_ChannelGetData(RchanL, buffer, length);

                                                          Result := c;
                                                          end;
                                                          procedure TForm1.Button2Click(Sender: TObject);
                                                          begin
                                                          rchanL := BASS_RecordStart(44100, 2, 0, Nil,nil);
                                                          pchan := BASS_StreamCreate(44100,2,0,@stream,0);
                                                          BASS_ChannelPlay(pchan,False);
                                                          end;

                                                          что я не учел?

                                                          Добавлено
                                                          так это же совсем не то...
                                                          Как воспроизвести тот канал который нужен с измененным уровнем звука?
                                                            Вы хотите отправлять записываемый звук сразу на воспроизведение? Т.е., организовать так называемый сквозной канал?
                                                              Вообще мне нужно записывать сигнал, который получаю от 2 источников, которые (сливаются) в стерео, программно их разделить, в случае необходимости уменьшить или увеличить входящий звук на обоих или отдельно на каждом из них, затем если пользователь нажмет прослушать, то воспроизводится ослабленный либо усиленный сигнал выбранного канала.
                                                              С вашей помощью я разобрал как вообще записывается сигнал, как его разделить, уменьшить звук, теперь мне осталось додумать индикатор, который дает знать какой уровень сигнала, зашкаливает, либо слабый, подумать над тем как при воспроизведении один (к примеру левый канал) сдублировать на правый(псевдо стерео)...

                                                              Добавлено
                                                              вот этот кусок дает мне индикатор, корректно?
                                                              procedure TForm1.Timer1Timer(Sender: TObject);

                                                              var
                                                              level,pl,pr:dword;

                                                              begin
                                                              level := BASS_ChannelGetLevel(rchanl);
                                                              pl := round(volume*loword(level)/32768*100);
                                                              cxTrackBar1.Position := 100-pl;
                                                                Прикреплённый файлПрикреплённый файлM.rar (28.33 Кбайт, скачиваний: 210) Вот то, что я накидал..
                                                                  Цитата
                                                                  подумать над тем как при воспроизведении один (к примеру левый канал) сдублировать на правый(псевдо стерео)...

                                                                  Он и так будет псевдостерео, моно потоки по умолчанию в общий микс примешиваются в равных пропорциях в левый и правый каналы. Наоборот, для того, чтобы развести по "ушам" моно, понадобиться изменить баланс соотвествующего потока.
                                                                  Допустим, вы создаёте поток для воспроизведения(моно, он же псевдостерео):
                                                                  ExpandedWrap disabled
                                                                    chan:=BASS_StreamCreate(44100,1,0,STREAMPROC_PUSH,nil);

                                                                  Для того, чтобы загнать его полностью в левый канал, надо изменить баланс(панораму) потока:
                                                                  ExpandedWrap disabled
                                                                    BASS_ChannelSetAttribute(chan,BASS_ATTRIB_PAN,-1); // -1 - левый канал,  +1 - правый канал. 0 - центр.


                                                                  Цитата
                                                                  затем если пользователь нажмет прослушать, то воспроизводится ослабленный либо усиленный сигнал выбранного канала.

                                                                  Я могу только примерно показать, как воспроизвести то, что вы записываете. Структуру программы - это вы сами.
                                                                  В StartRecording создайте поток для воспроизведения:
                                                                  ExpandedWrap disabled
                                                                        chan:=BASS_StreamCreate(44100,1,0,STREAMPROC_PUSH,nil);
                                                                        BASS_ChannelSetAttribute(chan,BASS_ATTRIB_PAN,-1); // баланс полностью выкрутить на левый канал
                                                                        p:=allocmem(16384);                           // згнать в поток пустой буфер длительностью где-то 0.2 с    
                                                                        Bass_StreamPutData(chan,P,16384);             // для того, чтобы звук не рвался
                                                                        freemem(p);                                    
                                                                        BASS_ChannelPlay(chan,false);          // запустить воспроизведение

                                                                  В StopRecording освобождаете:
                                                                  ExpandedWrap disabled
                                                                    BASS_ChannelStop(chan);
                                                                    BASS_StreamFree(chan);


                                                                  В RecordingCallback отправьте один из буферов, например, буфер левого канала, в поток воспроизведения:
                                                                  ExpandedWrap disabled
                                                                    BASS_StreamPutData(chan,buffer_L,length div 2);

                                                                  Можете отправить буфер на воспроизведение до изменения уровня сигнала, или после, отправить буфер левого или правого канала.
                                                                  На ваш вкус.

                                                                  Также в любой момент вы можете менять панораму для выбранного потока (воспроизведения) при помощи BASS_ChannelSetAttribute.

                                                                  Добавлено
                                                                  Цитата
                                                                  вот этот кусок дает мне индикатор, корректно?

                                                                  Не могу знать. Не знаю, для каких конкретно данных bass считает этот уровень, в справке не нашёл.
                                                                  А так, теоретически, вы получаете пиковый уровень на каком-то отрезке времени.
                                                                  Сообщение отредактировано: Prince -
                                                                    Цитата
                                                                    Вот то, что я накидал..

                                                                    Нет, что-то вы не то делаете.
                                                                    Файлы создаёте как бы моно. Потоки - стерео(но тоже как бы моно), и зачем-то два(?). И в кэлбеке неправильно выбираете данные канала.
                                                                      Попробовал замутить в примере ваши пожелания.
                                                                      Пока разбирался, столкнулся в очередной раз с интересной ситуацией. Она возникает, если использовать 2 девайса: с одного записывать, а выводить на другой. Поскольку устройства никак не синхронизированы, частоты их тактовых генераторов отличаются. Если частота тактового генератора(и частота дискретизации) устройства воспроизведения меньше частоты тактового генератора устройства записи, устройство воспроизедения не успевает воспроизводить всё, что ему отдаёт устройство записи, до получения очередной порции данных. Очередь воспроизведения постепенно и неуклонно растёт. Так получилось у меня. Выводил на блютуз нашники, записывал со встроенной карты ноутбука. В результате, за 1с в очереди воспроизведения набегает приблизительно 100 "неуспевших воспроизвестись" семплов. Очередь воспроизведения всё увеличивается, и задержка между тем, что записывается, и тем, что воспроизводится в данный момент, тоже. Оставил программу работать на сколько-то часов, и пока спал, получил вылет в Acces Violation.
                                                                      Чтобы это дело контролировать, специально вывел в строку статуса размер очереди воспроизведения каналов. Почитал справку по BASS_StreamPutData и выяснил примерно следущее: при каждом вызове BASS_StreamPutData сколько-то байт отправляется прямо в некий буфер воспроизведения канала(его размер можно регулировать, по умолчанию 500 мс), всё, что не влазит, записывается "в очередь" и учитывается внутри bass как-то отдельно. Поскольку в примере келбек канала записи срабатывает каждые примерно 10-50 мс, и в буфер каналов воспроизведения отсылаются кусочки такой же длительности, поначалу все данные влазят в буфер, и размер очереди(queue) каналов воспроизведения по нулям. Значения L/R_Queue по нулям. Спустя время буфер заполняется, и "хвосты" начинают появляться в queue.
                                                                      Если бы частота генератора устройства воспроизведения была больше, чем устройства записи, получилась бы другая картина: через время буфер воспроизведения опустел бы, и канал воспроизведения стал бы рвать звук.
                                                                      Чтобы избежать таких ситуаций, при работе с несколькими звуковыми картами придётся изобретать механизм "выравнивания" частот дискретизации, придётся либо прореживать периодически буфер воспроизведения, либо вставлять туда лишние семплы, в зависимости от разницы частот.
                                                                      Если записывать и воспроизводить на одном устройстве, таких проблем, в общем случае, не возникает.
                                                                      Прикреплённый файлПрикреплённый файлRecord_Playback_Test.rar (6.69 Кбайт, скачиваний: 223)
                                                                      Сообщение отредактировано: Prince -
                                                                        А ещё, даже связанные при помощи BASS_ChannelSetLink каналы, стартуют неодновременно. При прослушивании(Listen), если баланс каналов выставить по центру, на слух заметно "раздвоение" сигналов.
                                                                          Подскажите пожалуйста, что не правильно?
                                                                          var
                                                                          fTL:longint;
                                                                          fVolL:real;
                                                                          function RecordingCallbackL(Handle: HRECORD; buffer: Pointer; length: DWORD; user: Pointer): boolean; stdcall;
                                                                          var
                                                                          buffer_L: Pointer;
                                                                          psample: ^smallint;
                                                                          psample_L: ^smallint;
                                                                          i: cardinal;

                                                                          begin
                                                                          fTL := fTL + Length;

                                                                          buffer_L:=allocmem(length div 2);
                                                                          psample:=buffer;
                                                                          psample_L:=buffer_L;
                                                                          for i:=0 to length div 4-1 do
                                                                          Begin
                                                                          try
                                                                          psample_L^:=round(fVolL*psample^);
                                                                          except
                                                                          end;
                                                                          inc(psample);
                                                                          inc(psample_L);
                                                                          inc(psample);
                                                                          end;

                                                                          WaveStreamL.Write(buffer_L^, length div 2);
                                                                          freemem(buffer_L);
                                                                          Result := True;
                                                                          end;

                                                                          procedure TfrmMain.StartL;
                                                                          var s:string;
                                                                          begin
                                                                          if rchanL <> 0 then
                                                                          BASS_ChannelStop(rchanL);
                                                                          fVolL := cxVLeft.Position/100;
                                                                          with WaveHdr do
                                                                          begin
                                                                          wNumChannels := 1;
                                                                          wBlockAlign := 2;
                                                                          dwBytesPerSec := 88200;
                                                                          end;
                                                                          WaveStreamL := TFileStream.Create(b.RecLine1+getFileName('1'),fmcreate);
                                                                          WaveStreamL.Write(WaveHdr, SizeOf(WAVHDR));

                                                                          rchanL := BASS_RecordStart(44100, 2, 0, @RecordingCallbackL,nil);
                                                                          end;
                                                                          Выбивает ошибку...
                                                                          Прикреплённый файлПрикреплённый файлБезымянный.jpg (38.54 Кбайт, скачиваний: 622)
                                                                            Цитата
                                                                            Выбивает ошибку...

                                                                            В каком месте?

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

                                                                            Код в тег не забывайте оборачивать.


                                                                            Нет, Bass всё-таки знает про выходные линии микшера записи, они обозначаются у него индексом -1(минус один). А про то, что линии микшера могут иметь индивидуальные регулировки уровня для левого/правого каналов, bass не знает. У него есть только общая регулировка уровня для линии.
                                                                            Сообщение отредактировано: Prince -
                                                                              из за того что fTL - время я определил как longint, ну в общем заменил на double перестало...
                                                                              Спасибо вам большое! Без вас бы разбирался оочень долго...
                                                                              Я подробно изучу то, что вы мне отправили, потом отпишусь
                                                                                fTL:longint;
                                                                                fTL := fTL + Length;
                                                                                Поначалу тоже так подумал(что это неплохая идея), а потом прикинул, переполнение наступит через 6 часов записи(для беззнакового целого типа сardinal).

                                                                                Добавлено
                                                                                Цитата
                                                                                из за того что fTL - время я определил как longint,

                                                                                Странно, с чего бы... :scratch:

                                                                                Время можно брать от часов вреального времени, а длину файлового потока из свойства tfilestream.size. Там тип int64, так что и переполнение можно не учитывать на всех вменяемых длительностях записи. Просто сначала надо было проконтролировать длительность кусочков, так и поехало.
                                                                                Сообщение отредактировано: Prince -
                                                                                  Здорова! Ты был прав, там совсем не нужно было создавать несколько Rchan... все реализовал в одном...
                                                                                  Еще 2 вопроса..
                                                                                  1- Как отключить используя bass.dll звук линейного входа (ну к примеру запускаешь прогу на XP, и как подключил телефон через линейный выход, сразу идет вещание на выход)
                                                                                  2- Не понимаю почему, ооооч редко, но все же иногда вылетает исключение access violation при записи и одновременном прослушивании
                                                                                    Цитата
                                                                                    Как отключить используя bass.dll звук линейного входа

                                                                                    Для микшера воспроизведения, в типовой комплектации библиотеки такой возможности не нашёл(может, плохо искал).
                                                                                    Линии микшера записи можно дергать при помощи BASS_RecordSetInput. Включать, выключать, регулировать уровень сигнала.
                                                                                    Цитата
                                                                                    Не понимаю почему, ооооч редко, но все же иногда вылетает исключение access violation при записи и одновременном прослушивании

                                                                                    :-?
                                                                                    Сообщение отредактировано: Prince -
                                                                                      Спасибо тебе большое! Выручил! Ошибка выходила из-за ошибок в собственном коде... Все работает!
                                                                                        prince, не могу справиться с этой ошибкой... кстати, в том примере который ты скинул она тоже есть.. может из-за того что у меня win8 x64? напиши ко мне amanat_2007@mail.ru, помоги пожалуйста online
                                                                                          В каком месте дебагер ошибку показывает?
                                                                                            там такая ситуация...

                                                                                            ExpandedWrap disabled
                                                                                              form.create:
                                                                                                rchan := BASS_RecordStart(44100, 2,  10 shl 16, @RecordingCallback, nil);
                                                                                               
                                                                                              function RecordingCallback(Handle: HRECORD; buffer: Pointer; length: DWORD; user: Pointer): boolean; stdcall;
                                                                                               
                                                                                              var
                                                                                                buffer_L  :Pointer;
                                                                                                buffer_R  :Pointer;
                                                                                               
                                                                                                psample   :^smallint;
                                                                                                psample_L :^smallint;
                                                                                                psample_R :^smallint;
                                                                                                i:             cardinal;
                                                                                              begin
                                                                                               
                                                                                                 buffer_L:=allocmem(length div 2);
                                                                                                 buffer_R:=allocmem(length div 2);
                                                                                               
                                                                                                 psample:=buffer;
                                                                                                 psample_L:=buffer_L;
                                                                                                 psample_R:=buffer_R;
                                                                                               
                                                                                               
                                                                                                for i:=0 to length div 4-1 do
                                                                                                Begin
                                                                                                psample_L^:=round(psample^);
                                                                                                inc(psample);
                                                                                               
                                                                                                inc(psample_L);
                                                                                                psample_R^:=round(psample^);
                                                                                                inc(psample);
                                                                                               
                                                                                               
                                                                                                inc(psample_R);
                                                                                                end;
                                                                                                freemem(buffer_L);
                                                                                                freemem(buffer_R);
                                                                                                Result := True;
                                                                                              end;
                                                                                               
                                                                                              timer(200):
                                                                                                TimerAll.Enabled := false;
                                                                                                try
                                                                                                  inc(i);
                                                                                                  if i>2 then
                                                                                                    i:=1;
                                                                                                  if i=1 then
                                                                                                    begin
                                                                                                    cxGK1.Down := true;
                                                                                                    cxGK1Click(nil);
                                                                                                    end;
                                                                                                  if i=2 then
                                                                                                    begin
                                                                                                    cxGK2.Down := true;
                                                                                                    cxGK2Click(nil);
                                                                                                    end;
                                                                                                finally
                                                                                                  TimerAll.Enabled := true;
                                                                                                end;
                                                                                              cxGK1Click:
                                                                                                if cxGK1.Down then
                                                                                                    cxGK2.Down := false;
                                                                                              cxGK2Click:
                                                                                                if cxGK2.Down then
                                                                                                    cxGK1.Down := false;

                                                                                            Смысла не имеет данная прога... я упрощал по максимуму чтобы найти ошибку...
                                                                                            если запустить таймер и закоментировать rchan := BASS_RecordStart(44100, 2, 10 shl 16, @RecordingCallback, nil); ошибок нет
                                                                                            если выключить таймер ошибок так же нет
                                                                                            я использую компоненты devexspress...
                                                                                            у тебя в примере при отладке если нажимать быстро на checkbox listen, та же выходила...
                                                                                            но когда я откомпилировал и перенес на комп где win7 x86, ошибок не было

                                                                                            если можно взгляни пожалуйста по teamviewer
                                                                                            Прикреплённый файлПрикреплённый файлБезымянный.jpg (45.45 Кбайт, скачиваний: 586)
                                                                                            Сообщение отредактировано: D[u]fa -
                                                                                              Цитата
                                                                                              может из-за того что у меня win8 x64?

                                                                                              Да кто бы знал бы.

                                                                                              Цитата
                                                                                              если можно взгляни пожалуйста по teamviewer

                                                                                              Извините, :no-sad:.
                                                                                              Цитата
                                                                                              Безымянный.jpg

                                                                                              :-?
                                                                                              Цитата
                                                                                              закоментировать rchan := BASS_RecordStart(44100, 2, 10 shl 16, @RecordingCallback, nil); ошибок нет

                                                                                              Логично. Запись не выполняется, в кэлбек входа нет. По сути, программа ничего не выполняет.
                                                                                              Побробуйте увеличить интервал вызова кэлбек функции в BASS_RecordStart: вместо 10 поставьте 20, 30, 40, 50, 100 наконец. Это примерный интервал в мс между входами в RecordingCallback.
                                                                                              ExpandedWrap disabled
                                                                                                p:=allocmem(16384);
                                                                                                    Bass_StreamPutData(chan_L,P,16384);
                                                                                                    Bass_StreamPutData(chan_R,P,16384);

                                                                                              Заодно и в поток воспроизведения записать побольше данных в начале процесса, допустим, не меньше, чем length, возвращаемый в RecordingCallback(т.е., можно подсмотреть, а потом подкорректировать в StartRecording).

                                                                                              Гонял программу 2 часа, с прослушиванием и записью в файл, никаких вылетов. Единственная проблема, вылезла вновь рассинхронизация между потоками записи и воспроизведения. Как с этим бороться, сказать не могу, особоенно с учётом возможной передискретизации в ядре винды, или в недрах басс. Пока не знаю, что с этим делать. За 2 часа накопилось 12 кБайт "хвостов" в очереди воспроизведения.

                                                                                              Цитата
                                                                                              у тебя в примере при отладке если нажимать быстро на checkbox listen, та же выходила...

                                                                                              :-? У меня ничего такого не выходит. Отчего так может быть, без понятия. Значение listen копируется в локальную переменную при входе в RecordingCallback(во всяком случае, в архиве было так). До выхода из RecordingCallback изменения(даже если возникнут) никак не сказываются на результате работы RecordingCallback. Сам флаг лишь указывает, записывать в поток воспроизведения пустой буфер или с записанными данными. С выделением памяти(и её освобождением) флаг никак не связан.

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

                                                                                              когда пишите ответ, вверху формы есть выпадающий списк "code". Выделяеете ваш код, нажимаете на список, выбираете delphi/pascal. Читать сообщения будет удобней.
                                                                                              Сообщение отредактировано: Prince -
                                                                                                fTR:double

                                                                                                в RecordingCallback:
                                                                                                Цитата
                                                                                                pRecState(user).fTR := r.fTR;

                                                                                                в VisualUpdate:
                                                                                                Цитата
                                                                                                cxTimeR.Caption := timetostr(recstate.fTR);


                                                                                                Если производить запись примерно час, то вылетает ошибка access violation. Возможен вариант что в одном случае VisualUpdate пытается считать переменную fTR,а во втором RecordingCallback пытается записать, и из-за этого вылетает ошибка?
                                                                                                  Исходный код(без bass.dll)
                                                                                                  Прикреплённый файлПрикреплённый файлбез_cx.part01.rar (100 Кбайт, скачиваний: 211)
                                                                                                  Прикреплённый файлПрикреплённый файлбез_cx.part02.rar (100 Кбайт, скачиваний: 193)
                                                                                                  Прикреплённый файлПрикреплённый файлбез_cx.part03.rar (20.07 Кбайт, скачиваний: 193)
                                                                                                    Нет никаких предложений? :(
                                                                                                      Все... закончил. Ошибка возникала из-за использования postMessage... если visualupdate выполняется дольше 100мс, либо если форме будет послано сообщение, которое будет перекрывать все остальные(например вызов контекстного меню или когда выбираешь дату в dateTimePiker или например когда нажимаешь на рамку окна чтобы его перенести) очередь растет и потом может дать сбой... в твоем примере тоже если разрешить разворачивать окно и долго играться сворачивать и разворачивать можно получить исключение типа access violation.
                                                                                                      В общем перевел все на потоки и все работает как часики.
                                                                                                      Спасибо большое еще раз за помощь!
                                                                                                      1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                                                                      0 пользователей:


                                                                                                      Рейтинг@Mail.ru
                                                                                                      [ Script execution time: 0.1774 ]   [ 26 queries used ]   [ Generated: 12.07.26, 19:04 GMT ]