Запись потока с линейного входа
, Разделить поток линейного входа на 2 разных в первом только левое моно, а во втором только правое моно
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.50] |
|
|
ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Запись потока с линейного входа
, Разделить поток линейного входа на 2 разных в первом только левое моно, а во втором только правое моно
|
Сообщ.
#1
,
|
|
|
|
Здравствуйте...
Есть, к примеру, телефон, я его подключаю к звуковой карте на линейный вход... мне нужно входящий стерео поток разделить на 2 моно, то есть в первом будет только то что было на левом канале, а во втором только то, что на правом канале... и записывать эти потоки в 2 разных файла. Я почитал bass.dll, посмотрел примеры, но так и не разобрался.... Помогите пожалуйста разобраться... Заранее спасибо! |
|
Сообщ.
#2
,
|
|
|
|
Цитата sandist @ но так и не разобрался.... Необходимо при открытии устройства указать, что будут два канала: ![]() ![]() //Создаем заголовок для открытия устройства вывода WaveFormat.wFormatTag := WAVE_FORMAT_PCM; WaveFormat.nChannels := 1; //Выбор 1 канал моно ...... WaveOut := New(PHWaveOut); //Делаем попытку открыть устройство //Возможно ИС при занятом устройстве //придется перехватывать Err := WaveOutOpen(WaveOut, 0, @WaveFormat, Handle, 0, CALLBACK_WINDOW); |
|
Сообщ.
#3
,
|
|
|
|
Цитата Я почитал bass.dll, посмотрел примеры, но так и не разобрался.... Помогите пожалуйста разобраться... Цитата WaveOutOpen для захвата Медвед, что это было? Добавлено Цитата и записывать эти потоки в 2 разных файла. Я почитал bass.dll, посмотрел примеры, но так и не разобрался.... Помогите пожалуйста разобраться... Разобраться с чем конкретно? Что вызывает трудность? |
|
Сообщ.
#4
,
|
|
|
|
Цитата Prince @ Медвед, что это было? Комментарий к коду читай. Непонятно? Тогда расшифрую: в коде показано, где формировать количество каналов. Тебе что непонятно то? |
|
Сообщ.
#5
,
|
|
|
|
Мне непонятно, как человек, не разобравшийся в примерах из справки к басс, сможет из комментариев к вырванному из другой оперы кусочку кода, совершенно неинформативному в контексте поставленных вопросов, понять, как "входящий стерео поток разделить на 2 моно, то есть в первом будет только то что было на левом канале, а во втором только то, что на правом канале... и записывать эти потоки в 2 разных файла". Вот непонятно мне.
|
|
Сообщ.
#6
,
|
|
|
|
Цитата Prince @ Мне непонятно Т.е. к тому, как сделать так, чтобы был захват ДВУХ каналов у тебя вопросов в контексте моего ответа нет, так? Может подождем автора, убедимся, что он осознал, КАК сделать захват двух каналов при помощи формирования определенной структуры и пойдем далее? Например, отслеживая по флагу чет-нечет и запихивая пришедшие буферы в разные потоки. Но для начала настроить микшер. Или это тебе тоже непонятно? Цитата Prince @ Вот непонятно мне. ![]() Мир даже не заметил твоей тревоги.... Тебе это странно, мне....как то не очень. И это тоже странно? Добавлено Цитата Prince @ не разобравшийся в примерах из справки к басс Кстати, Prince, я вот ни разу не разбирался с этой длл. Но тем не менее не испытываю никаких напряжений в работе со звуком. Тоже странно? |
|
Сообщ.
#7
,
|
|
|
|
Цитата Т.е. к тому, как сделать так, чтобы был захват ДВУХ каналов у тебя вопросов в контексте моего ответа нет, так? А вот и не угадал. Есть. Каким боком WaveOutOpen относится к захвату хоть скольких-нибудь каналов? Цитата Может подождем автора, убедимся, что он осознал, КАК сделать захват двух каналов при помощи формирования определенной структуры и пойдем далее? Да подождём, конечно. |
|
Сообщ.
#8
,
|
|
|
|
Цитата Prince @ Каким боком WaveOutOpen относится к захвату хоть скольких-нибудь каналов? Никаким. Так же как и WaveInOpen. И? |
|
Сообщ.
#9
,
|
|
|
|
Цитата Никаким. Так же как и WaveInOpen Это как. Почему WaveInOpen никаким? |
|
Сообщ.
#10
,
|
|
|
|
Цитата Prince @ Почему WaveInOpen никаким? Т.е. с WaveOutOpen ты согласен? |
|
Сообщ.
#11
,
|
|
|
|
Цитата Т.е. с WaveOutOpen ты согласен? С тем, что ты сморозил чепуху, с этим WaveOutOpen, конечно, согласен. |
|
Сообщ.
#12
,
|
|
|
|
Спасибо что откликнулись!
Я далек от программирования звука, а так с лету понять видимо мозгов мало 😊 Если можно дайте мне хоть направление, куда копать, функцию или компонент... Поток данных идет от телефона, на линейный вход, я понял как записывать этот поток, в файле он идет как моно... А как записывать только один канал, ну или вообще накладывать какие-либо фильтры или эффекты на сам поток, не понял Например мне нужно чтобы это стереопоток разбивался, записывался в разные файлы, при этом чтобы он соазу не выводился на выход, а была возможность какой-то из разбитых ранее потоков отдельно в случае необходимости выводить на выходе... Я знаю что надо, но обсалютно не имеею представления с какого конца подойти к этой проблеме... Помогите пожалуйста!!!!!!!!!! |
|
Сообщ.
#13
,
|
|
|
|
Цитата Prince @ С тем, что ты сморозил чепуху, с этим WaveOutOpen, конечно, согласен Я пожалуй соглашусь с тем, что ты не разобравшись, что я хотел показать, начал гнать пургу. Это так на тебя похоже, и перед твоими "доводами" блекнет любая "чепуха". Цитата sandist @ Поток данных идет от телефона, на линейный вход Он идет стерео или моно? Или моно но по двум проводам? Это принципиально, т.к. из моно ты стерео не получишь. Максимум - два одинаковых канала. Это раз. Цитата sandist @ А как записывать только один канал 1. Сначала формируешь структуру и открываешь устройство. Что за структура и как ее формировать для открытия как одного так и двух каналов, я показал. Правда "светочи" вцепились в вывод, "аргументируя" необходимостью ввода, но сознательно упуская одну деталь - структура одинакова как для ввода, так и для вывода. По крайней мере в части количества каналов. 2. Далее ты подготавливаешь "карусель" из буферов размером 1024 байт и фиксируешь их в очереди драйвера. 3. Запускаешь открытое устройство на работу и "карусель" начнет тебе выдавать данные. Твоя задача - корректно данные из буфера принять и слить в поток. Если необходимо писать разные каналы раздельно, то что мешает четные буферы сливать в один поток, а нечетные в другой? Совсем подробно все это разжевано здесь. Но повторю, чтобы у тебя был захват необходимого устройства (микрофона/линейного входа) необходимо сначала настроить подсистему микширования, активировав необходимую линию. |
|
Сообщ.
#14
,
|
|
|
|
Стерео поток на вход идет... А можно сделать так, чтобы со входа звук сразу не шел выход... А если будет нужно пустить на выход один из этих потоков?
Добавлено Если можно дай пожалуйста более конкретный пример... Оч большая просьба Добавлено Да ты прав! По двум проводам моно Добавлено А в чем разница? Задача стоит так, идет с 2 микрофонов моно, подаются на вход и выходит стерео... А про телефон я сказал потому что дома испытываю результат на стерео музыке, считал что это равнозначно |
|
Сообщ.
#15
,
|
|
|
|
Цитата sandist @ Если можно дай пожалуйста более конкретный пример... Оч большая просьба Мыло в приват - сброшу пример работы с микрофоном и пример настройки микшера на линейный вход на Д7. Как собрать необходимое тебе из двух примеров, добавив раздельную запись потоков на винт - не вижу никаких проблем. Добавлено Цитата sandist @ Задача стоит так, идет с 2 микрофонов моно, подаются на вход и выходит стерео... Нет проблем. |
|
Сообщ.
#16
,
|
|
|
|
Цитата Например мне нужно чтобы это стереопоток разбивался, записывался в разные файлы Прикреплённый файл Копия_RecordTest.rar (3.54 Кбайт, скачиваний: 405)
За основу взят пример из Bass. Захват аудио производится в формате 44100 стерео 16 бит, а на диск пишется сразу 3 файла: стерео, и отдельно левый/правый каналы. Файлы моно имеют в имени приставку L/R. Добавлено Цитата при этом чтобы он соазу не выводился на выход, а была возможность какой-то из разбитых ранее потоков отдельно в случае необходимости выводить на выходе... Переведите. |
|
Сообщ.
#17
,
|
|
|
|
Цитата Я пожалуй соглашусь с тем, что ты не разобравшись, что я хотел показать, начал гнать пургу. Да, таки ты не подумав, начал гнать пургу, и не можешь в этом признаться. Цитата Правда "светочи" вцепились в вывод, "аргументируя" необходимостью ввода, но сознательно упуская одну деталь - структура одинакова как для ввода, так и для вывода. Светочи вцепились в то, что ты выдал ерунду, и как обычно, уперто твердишь, что ты прав, просто тебя неправильно поняли. |
|
Сообщ.
#18
,
|
|
|
|
Попробую перевести... я подключаю телефон, где играет стерео, на линейный вход, на той же звуковухе подключаю наушники на линейный выход и слышу музыку... а нужно чтобы ее по умолчанию слышно не было, а было слышно только то, что я сам решу выводить... ну к примеру один из входных потоков...
И еще один вопрос, я запускаю на этом же компе плеер и то, что играет на плеере тоже попадает на запись... накладывается на то, что приходит с линейного входа, как этого избежать? |
|
Сообщ.
#19
,
|
|
|
|
Цитата sandist @ как этого избежать? Я же тебе говорю - микшер. Погаси в микшере выходной канал и ты ничего в наушниках не услышишь. Аналогично и с выбором входа для звука. Цитата Prince @ и как обычно, уперто твердишь Ну если светочи непонятливые то как же не твердить то? Ведь белое не станет черным, как бы этого "светочам" не хотелось... Цитата Prince @ просто тебя неправильно поняли. Уже теплее, продолжай. Я зачту слив. |
|
Сообщ.
#20
,
|
|
|
|
Цитата Я зачту слив. Зачти его себе, я тебе его уже зачёл на прошлой странице. Добавлено Цитата Попробую перевести... я подключаю телефон, где играет стерео, на линейный вход, на той же звуковухе подключаю наушники на линейный выход и слышу музыку...а нужно чтобы ее по умолчанию слышно не было Выключить в микшере прослушивание линии линейного входа. Цитата а было слышно только то, что я сам решу выводить... ну к примеру один из входных потоков... Можно сделать програмно, но с задержкой относительно входящего аудио-сигнала. Цитата И еще один вопрос, я запускаю на этом же компе плеер и то, что играет на плеере тоже попадает на запись... накладывается на то, что приходит с линейного входа, как этого избежать? Выключить в микшере запись с линии стерео-выхода или выключить в микшере прослушивание линии линейного входа. Я через форум не могу поковыряться в настройках вашего микшера, а там могут быть варианты. |
|
Сообщ.
#21
,
|
|
|
|
Спасибо большое!!! разобрался... но чувствую еще этих вопросов много будет
|
|
Сообщ.
#22
,
|
|
|
|
Ошибку допустил в function RecordingCallback:
![]() ![]() Form1.WaveStreamL.Write(buffer_L^, length div 2); Form1.WaveStreamR.Write(buffer_L^, length div 2); Во второй строчке должен быть buffer_R^ В TForm1.FormClose добавить ![]() ![]() if BASS_ChannelIsActive(rchan) <> 0 then brecord.Click; иначе, если закрыть окно во время записи, ресурсы не особождаются корректно. Обновил архив. |
|
Сообщ.
#23
,
|
|
|
|
Подскажите пожалуйста еще... насчет того как проигрывать через bass.dll много чего написано, а вот с записью куда скуднее..
Вы подсказали мне как разделить поток и записывать их в файлы.. а как разбить поток на 2, так, чтобы к ним можно было применять эффекты, ну вернее громкость, эквалайзер. Например я записываю звук, а он от источника очень громкий... нужно эквалайзером уменьшить |
|
Сообщ.
#24
,
|
|||||||||||||||||||||||||||
|
|
Цитата Вы подсказали мне как разделить поток и записывать их в файлы.. а как разбить поток на 2 Вопрос бессмысленный. Разбить, разделить - масло масляное. У вас есть кусок памяти(буфер, массив, обзовите как угодно), в котором отсчёты каналов располагаются так:
Каждый отсчёт - 16 бит(2 байтовое число со знаком). Читайте нужные вам отсчёты и обрабатывайте как вам угодно. В примере, для того, чтобы записывать в файлы отдельно левый/правый каналы, выделяются дополнительно 2 буфера, куда раскидываются отсчёты из стерео буфера.
Потом все три буфера сливаются на диск, в разные файлы. Цитата Например я записываю звук, а он от источника очень громкий... "Регулятор покрути". На источнике, чтобы согласовать по уровню выход источника и вход звуковой карты; и в микшере звуковой карты, чтобы выставить требуемый уровень записываемого сигнала. Цитата а как разбить поток на 2, так, чтобы к ним можно было применять эффекты, ну вернее громкость, эквалайзер Допустим, применили. А дальше? |
|
Сообщ.
#25
,
|
|
|
|
Как реализовано в примере я понял, но по условию у меня может быть с левого источника громкий звук, а с правого тихий, мне нужно уменьшить к примеру левый... то есть подается стерео звук, но на левом канале нужно уменьшить, на источнике покрутить не вариант, в микшере как я уменьшу именно для левого?
А нельзя получить данные, их преобразовать и уже потом записывать? Времени совсем мало, если можно конкретный пример... Спасибо |
|
Сообщ.
#26
,
|
|
|
|
Цитата sandist @ в микшере как я уменьшу именно для левого? Баланс при воспроизведении не прокатит? |
|
Сообщ.
#27
,
|
|
|
|
![]() ![]() 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 секцию, но раз времени мало, пусть будет так. |
|
Сообщ.
#28
,
|
|
|
|
Спасибо большое! Еще если можно помогите воспроизвести выбраный канал... вот пробую так, но у меня звук прерывается
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; что я не учел? Добавлено так это же совсем не то... Как воспроизвести тот канал который нужен с измененным уровнем звука? |
|
Сообщ.
#29
,
|
|
|
|
Вы хотите отправлять записываемый звук сразу на воспроизведение? Т.е., организовать так называемый сквозной канал?
|
|
Сообщ.
#30
,
|
|
|
|
Вообще мне нужно записывать сигнал, который получаю от 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; |
|
Сообщ.
#32
,
|
|
|
|
Цитата подумать над тем как при воспроизведении один (к примеру левый канал) сдублировать на правый(псевдо стерео)... Он и так будет псевдостерео, моно потоки по умолчанию в общий микс примешиваются в равных пропорциях в левый и правый каналы. Наоборот, для того, чтобы развести по "ушам" моно, понадобиться изменить баланс соотвествующего потока. Допустим, вы создаёте поток для воспроизведения(моно, он же псевдостерео): ![]() ![]() chan:=BASS_StreamCreate(44100,1,0,STREAMPROC_PUSH,nil); Для того, чтобы загнать его полностью в левый канал, надо изменить баланс(панораму) потока: ![]() ![]() BASS_ChannelSetAttribute(chan,BASS_ATTRIB_PAN,-1); // -1 - левый канал, +1 - правый канал. 0 - центр. Цитата затем если пользователь нажмет прослушать, то воспроизводится ослабленный либо усиленный сигнал выбранного канала. Я могу только примерно показать, как воспроизвести то, что вы записываете. Структуру программы - это вы сами. В StartRecording создайте поток для воспроизведения: ![]() ![]() 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 освобождаете: ![]() ![]() BASS_ChannelStop(chan); BASS_StreamFree(chan); В RecordingCallback отправьте один из буферов, например, буфер левого канала, в поток воспроизведения: ![]() ![]() BASS_StreamPutData(chan,buffer_L,length div 2); Можете отправить буфер на воспроизведение до изменения уровня сигнала, или после, отправить буфер левого или правого канала. На ваш вкус. Также в любой момент вы можете менять панораму для выбранного потока (воспроизведения) при помощи BASS_ChannelSetAttribute. Добавлено Цитата вот этот кусок дает мне индикатор, корректно? Не могу знать. Не знаю, для каких конкретно данных bass считает этот уровень, в справке не нашёл. А так, теоретически, вы получаете пиковый уровень на каком-то отрезке времени. |
|
Сообщ.
#33
,
|
|
|
|
Цитата Вот то, что я накидал.. Нет, что-то вы не то делаете. Файлы создаёте как бы моно. Потоки - стерео(но тоже как бы моно), и зачем-то два(?). И в кэлбеке неправильно выбираете данные канала. |
|
Сообщ.
#34
,
|
|
|
|
Попробовал замутить в примере ваши пожелания.
Пока разбирался, столкнулся в очередной раз с интересной ситуацией. Она возникает, если использовать 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)
|
|
Сообщ.
#35
,
|
|
|
|
А ещё, даже связанные при помощи BASS_ChannelSetLink каналы, стартуют неодновременно. При прослушивании(Listen), если баланс каналов выставить по центру, на слух заметно "раздвоение" сигналов.
|
|
Сообщ.
#36
,
|
|
|
|
Подскажите пожалуйста, что не правильно?
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)
|
|
Сообщ.
#37
,
|
|
|
|
Цитата Выбивает ошибку... В каком месте? По-человески было бы балансировку громкости и собственно громкость каналов регулировать при помощи функций микшера. Я сделал так как вы просили, т.е., чтобы можно было регулировать уровень звука в потоке, потому что вы спрашивали, как это сделать, и потому что bass, похоже, ничего не знает о выходных линиях микшера(а может, я просто не разобрался). Но в принципе, не проблема добавить управление балансом и уровнем записи, если сам микшер имеет контролы для таких манипуляций. Потому что если поток изначально записан перегруженым, уменьшай-не уменьшай уровень звука в нём, звук всё равно искаженным будет. Код в тег не забывайте оборачивать. Нет, Bass всё-таки знает про выходные линии микшера записи, они обозначаются у него индексом -1(минус один). А про то, что линии микшера могут иметь индивидуальные регулировки уровня для левого/правого каналов, bass не знает. У него есть только общая регулировка уровня для линии. |
|
|
|
|
|
из за того что fTL - время я определил как longint, ну в общем заменил на double перестало...
Спасибо вам большое! Без вас бы разбирался оочень долго... Я подробно изучу то, что вы мне отправили, потом отпишусь |
|
Сообщ.
#39
,
|
|
|
|
fTL:longint;
fTL := fTL + Length; Поначалу тоже так подумал(что это неплохая идея), а потом прикинул, переполнение наступит через 6 часов записи(для беззнакового целого типа сardinal). Добавлено Цитата из за того что fTL - время я определил как longint, Странно, с чего бы... ![]() Время можно брать от часов вреального времени, а длину файлового потока из свойства tfilestream.size. Там тип int64, так что и переполнение можно не учитывать на всех вменяемых длительностях записи. Просто сначала надо было проконтролировать длительность кусочков, так и поехало. |
|
Сообщ.
#40
,
|
|
|
|
Здорова! Ты был прав, там совсем не нужно было создавать несколько Rchan... все реализовал в одном...
Еще 2 вопроса.. 1- Как отключить используя bass.dll звук линейного входа (ну к примеру запускаешь прогу на XP, и как подключил телефон через линейный выход, сразу идет вещание на выход) 2- Не понимаю почему, ооооч редко, но все же иногда вылетает исключение access violation при записи и одновременном прослушивании |
|
Сообщ.
#41
,
|
|
|
|
Цитата Как отключить используя bass.dll звук линейного входа Для микшера воспроизведения, в типовой комплектации библиотеки такой возможности не нашёл(может, плохо искал). Линии микшера записи можно дергать при помощи BASS_RecordSetInput. Включать, выключать, регулировать уровень сигнала. Цитата Не понимаю почему, ооооч редко, но все же иногда вылетает исключение access violation при записи и одновременном прослушивании |
|
|
|
|
|
Спасибо тебе большое! Выручил! Ошибка выходила из-за ошибок в собственном коде... Все работает!
|
|
Сообщ.
#43
,
|
|
|
|
prince, не могу справиться с этой ошибкой... кстати, в том примере который ты скинул она тоже есть.. может из-за того что у меня win8 x64? напиши ко мне amanat_2007@mail.ru, помоги пожалуйста online
|
|
Сообщ.
#44
,
|
|
|
|
В каком месте дебагер ошибку показывает?
|
|
Сообщ.
#45
,
|
|
|
|
там такая ситуация...
![]() ![]() 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)
|
|
Сообщ.
#46
,
|
|
|
|
Цитата может из-за того что у меня win8 x64? Да кто бы знал бы. Цитата если можно взгляни пожалуйста по teamviewer Извините, .Цитата Безымянный.jpg ![]() Цитата закоментировать rchan := BASS_RecordStart(44100, 2, 10 shl 16, @RecordingCallback, nil); ошибок нет Логично. Запись не выполняется, в кэлбек входа нет. По сути, программа ничего не выполняет. Побробуйте увеличить интервал вызова кэлбек функции в BASS_RecordStart: вместо 10 поставьте 20, 30, 40, 50, 100 наконец. Это примерный интервал в мс между входами в RecordingCallback. ![]() ![]() 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. Читать сообщения будет удобней. |
|
Сообщ.
#47
,
|
|
|
|
fTR:double
в RecordingCallback: Цитата pRecState(user).fTR := r.fTR; в VisualUpdate: Цитата cxTimeR.Caption := timetostr(recstate.fTR); Если производить запись примерно час, то вылетает ошибка access violation. Возможен вариант что в одном случае VisualUpdate пытается считать переменную fTR,а во втором RecordingCallback пытается записать, и из-за этого вылетает ошибка? |
|
Сообщ.
#48
,
|
|
|
|
Исходный код(без bass.dll)
Прикреплённый файл без_cx.part01.rar (100 Кбайт, скачиваний: 211)
Прикреплённый файл без_cx.part02.rar (100 Кбайт, скачиваний: 193)
Прикреплённый файл без_cx.part03.rar (20.07 Кбайт, скачиваний: 193)
|
|
Сообщ.
#49
,
|
|
|
|
Нет никаких предложений?
|
|
Сообщ.
#50
,
|
|
|
|
Все... закончил. Ошибка возникала из-за использования postMessage... если visualupdate выполняется дольше 100мс, либо если форме будет послано сообщение, которое будет перекрывать все остальные(например вызов контекстного меню или когда выбираешь дату в dateTimePiker или например когда нажимаешь на рамку окна чтобы его перенести) очередь растет и потом может дать сбой... в твоем примере тоже если разрешить разворачивать окно и долго играться сворачивать и разворачивать можно получить исключение типа access violation.
В общем перевел все на потоки и все работает как часики. Спасибо большое еще раз за помощь! |