Вход

Просмотр полной версии : AY-player для linyx?



SMT
29.01.2006, 20:18
чем пользуются линуксоиды для прослушивания AY-музык (или им не надо?). сейчас просто сделал библиотечку для эмуляции ковоксов, биперов, AY-ков и т.п. получилась очень маленькая, совсем не жрущая cpu (в отличие от известных winamp-плагина и плейера), легкая в использовании. как пример я сделал консольный VTX-плейер (приинклюдив исходники архиватора AR для распаковки LHA, 89-го года, полдня фиксил баги после перекомпиляции его в 32 бита)

это я к чему. плейер играет музыку через единственную функцию "отдать блок на воспроизведение", что можно заменить в линуксе на свою (даже запись семплов в спец-файл /dev/<чего-то-там> подойдёт). пока вместо плей-листов можно использовать shell-скрипт, запустив плейер по очереди с разными файлами

дальше, если прилепить любое ядро эмуляции Z80, можно проиграть и PT3/STP/STC/PT2... всё, что умеет, к примеру, ZX-Amp (если загрузить в эмулятор его плейер)

интересно услышать, насколько нужен полноценный плейер (для windows-то уже есть), с определением времени воспроизведения AY и SNA-файлов, перемоткой и пр.

если появятся желающие, можно будет начать делать на 2 платформы - универсальная билиотека + на её основе плагины к винампу и там не знаю к чему на линуксе плагины есть

вот версия для win32 с исходниками и набором музык

Электрик
29.01.2006, 20:41
Плагин для XMMS под один AY-формат уже есть - SquareTone. Там правда PT3, а тут VTX - и там и там надо конвертить, а это suxx. :mad: Вот чего бы мне хотелось - плагин с синтезом от AY_Emul и всеми его фишками прилепленный к винампу, foobar2000 или линуксовому XMMS. Всёж таки приятнее, когда всё в одной программе. :rolleyes:

Кстати, AY_Emul прекрасно пашет под Wine.

По поводу быстродействия кстати поясни - как может эмуляция AY и CPU (я правильно понял?) быть быстрее только эмуляции AY?

boo_boo
29.01.2006, 21:03
чем пользуются линуксоиды для прослушивания AY-музык (или им не надо?). ехем... aylet'om, который только .ay файлы играет... довольно малорадостная штука ))


сейчас просто сделал библиотечку для эмуляции ковоксов, биперов, AY-ков и т.п. получилась очень маленькая, совсем не жрущая cpu (в отличие от известных winamp-плагина и плейера), легкая в использовании. как пример я сделал консольный VTX-плейер (приинклюдив исходники архиватора AR для распаковки LHA, 89-го года, полдня фиксил баги после перекомпиляции его в 32 бита)
о, здорово, сталбыть не придется сорцы US корежить, чтобы нормальную AYку сделать в эмуле :)


если появятся желающие, можно будет начать делать на 2 платформы - универсальная билиотека + на её основе плагины к винампу и там не знаю к чему на линуксе плагины есть

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

SMT
29.01.2006, 22:14
не соберётся - другой смысл у прагмы pack с 2-мя параметрами
pack(push, 1) на MSVC будет ждать парный pack(pop, 1), т.е. 1 тут - просто идентификатор

самое странное - замена

union SNDSAMPLE
{
DWORD sample; // left/right channels in low/high WORDs
struct { WORD left, right; }; // or left/right separately
};
на

union SNDSAMPLE
{
DWORD sample; // left/right channels in low/high WORDs
struct rl { WORD left, right; }; // or left/right separately
};
как оно скомпилировалось? ведь 2-й вариант определяет описание класса rl внутри пространства имён SNDSAMPLE, но не объявляет внутри SNDSAMPLE экземпляр rl. т.е. код sample.left - ошибочный (не компилируется MSVC)
предлагаю

struct SNDCHANNELS
{
WORD left, right;
};

union SNDSAMPLE
{
DWORD sample; // left/right channels in low/high WORDs
SNDCHANNELS ch; // or left/right separately
}; - должно везде собираться
странно, почему const не работает. на самом деле те константы типа unsigned, они передаются в unsigned-параметры функций (хотя msvc не выдаёт warning'ов и при int), но они могут вдруг использоваться и в сравнениях
вариант
const unsigned TICK_FF=6; компилируется gcc?


я -- желающий
ну попробуй LHA-депакер портировать..


Кстати, AY_Emul прекрасно пашет под Wine.а, значит, не особо нужно


По поводу быстродействия кстати поясни - как может эмуляция AY и CPU (я правильно понял?) быть быстрее только эмуляции AY?так сделать медленнее - не проблема ;-) особенно когда надо сделать чтобы быстрее заработало

SMT
29.01.2006, 22:25
попробовал скомпилить само ядро (sndrender) под линухом, через пять минут правки кода собралось (ессно, работает ли -- не проверял, для этого еще и сам плеер нужно портировать или плагин к xmms писать, но не вижу причин, чтоб не работало).
а ты раскомментируй запись семплов в файл и сотри запись в звукарту. потом открой эти raw data каким-нить звуковым редактором

boo_boo
29.01.2006, 23:02
не соберётся - другой смысл у прагмы pack с 2-мя параметрами
pack(push, 1) на MSVC будет ждать парный pack(pop, 1), т.е. 1 тут - просто идентификатор а GCC этот параметр воспринимает как новый alignment. и прагму пуш без параметра GCC (по крайней мере 3.3.2) не ест. сталбыть ifdef'ами это хозяйство...


самое странное - замена

union SNDSAMPLE
{
DWORD sample; // left/right channels in low/high WORDs
struct { WORD left, right; }; // or left/right separately
};
на

union SNDSAMPLE
{
DWORD sample; // left/right channels in low/high WORDs
struct rl { WORD left, right; }; // or left/right separately
};
как оно скомпилировалось? ведь 2-й вариант определяет описание класса rl внутри пространства имён SNDSAMPLE, но не объявляет внутри SNDSAMPLE экземпляр rl. т.е. код sample.left - ошибочный (не компилируется MSVC)
да, глючу %)...
чтобы пропер вариант с именованным экземпляром структуры, объявлять ее отдельно не надо. (но в коде придется вместо sample.left писать sample.ch.left)


вариант
const unsigned TICK_FF=6; компилируется gcc?
ага, главное, чтоб тип был.


ну попробуй LHA-депакер портировать..
ок, займусь

+sndrender: сейчас собирается MSVC?

boo_boo
30.01.2006, 00:11
а ты раскомментируй запись семплов в файл и сотри запись в звукарту. потом открой эти raw data каким-нить звуковым редакторомготово. все вроде ок, но форма волны какая-то странная (см картинку) -- ужатая в половину диапазона.

newart
30.01.2006, 03:55
Кто-нибудь может написать простейшую DLL для проигрывания
VTX? (ну или PSG).
Для c64 есть, а для AY все никто не может написать, обидно.

SMT
30.01.2006, 07:52
DLL с каким интерфейсом?

boo_boo
30.01.2006, 08:29
насчет формы волны -- хм, оказывается, она во всех плеерах и эмуляторах такая... почему, интересно? звук 8и битным по сути выходит...

upd. даа, спать надо больше... не 8и битным, а 15и )

SMT
30.01.2006, 08:38
готово. все вроде окв глюкалке я подсмотрел, что запись в семплов в файл /dev/dsp даёт звук. правда, перед этим там делается ioctl для установки частоты оцифровки

там, кстати, ошибка: SOUND_ARRAY_LEN=1000, когда теоретически за кадр пентагон может сделать 71680t/7t > 10000 записей в регистры, в турбе - вдвое больше. просто повезло, что нет программы, состоящей подряд из одних out'ов в порт AY

и там в каждом кадре выдаётся одинаковое число семлов (SOUND_TICKS_PER_FRAME), когда SNDRENDER может выдавать переменное число (в пределах +-1), причём разное для разных источников (AY, beeper, ...) сейчас вот думаю, сделать чтоли класс, суммирующий такие потоки


ужатая в половину диапазона
сам чип однополярный (питается 0,+5). эмулятор даёт диапазон от 0 до global volume (в плейере #7FFF). хотелось совместить "тишину" чипа с нулевой громкостью

раньше в unreal использовался диапазон -#8000..#7FFF - были щелчки на макс. громкости (переход -#8000 <--> 0) при входе в отладчик, диалоги и т.п.

если так важно, попробуй прикрутить дифференцирование и усиление к сигналу


сейчас собирается MSVC?
да, вот

SMT
30.01.2006, 09:37
в-общем, надо вынести в отдельный файл различия, чтобы по 10 раз не менять

boo_boo
30.01.2006, 17:42
вот, прикрутил линуховый звук... заодно сделал цикл по именам файлов, чтоб "vtxplay *" можно было делать. слушаю :)
блин, SMT, РЕСПЕКТ! наконец-то музыку можно послушать нормально.
напишу плагин к xmms (или beep?), ей-ей напишу ;)

newart
30.01.2006, 17:55
DLL с каким интерфейсом?
Я в этих делах не очень шарю.
Хватит вполне что-то типа Midas11.Dll
Play, Volume, ну и чтобы перемотать можно было в произвольный отрезок.

Sinus
30.01.2006, 20:08
надо будет ещё такую фишку сделать:
прикрутить туда ядро z80 и бульбовский плеер для zx, чтоб PT2 PT3 можно было слушать.

ну или как нибудь по другому (может так сделать как в AyEmul-e ?) чтоб не только vtx-ы можно слушать было.

ибо ломает конвертить.

SMT
30.01.2006, 22:27
вот думаю сделать класс Song с методами load_from_file (с авто-определением формата), getlenght, get/set_property (такие, как автор, год, название и т.п.)
и класс Player с методами load(Song), seek, PlayToBuffer (выдаёт небольшой кусок звука в буфер, периодически вызывая, можно собрать всю песню), get_position

правда, такой интерфейс будет доступен только из c++, заворачивать в dll - это написать переходник для каждого метода, включая конструкторы/деструкторы. думаю, при реальной необходимости это сделает тот, кому это надо (если не захочет юзать c++) - писанины будет много, но вся она однотипная

newart
30.01.2006, 22:49
думаю, при реальной необходимости это сделает тот, кому это надо
Короче как всегда.

elf/2
31.01.2006, 11:13
вот думаю сделать класс Song с методами load_from_file (с авто-определением формата)

а можно автоопределение формата в отдельный метод вынести? и добавить выдирание метаинформации из файла (автор, название, tracker, с плеером или без и т.д.) отдельным методом


правда, такой интерфейс будет доступен только из c++, заворачивать в dll - это написать переходник для каждого метода, включая конструкторы/деструкторы.

а автогенерировать такую plain C обертку нельзя?

SMT
31.01.2006, 13:24
автогенерировать такую plain C обертку нельзя?
например, чем? для метода int Player::LoadSong(Song *song) сделать

__declspec(dllexport) __stdcall int Player_LoadSong(int hPlayer, int hSong)
{
return ((Player*)hPlayer)->LoadSong((Song*)hSong);
}написать генерилку сложнее, чем самому всё проделать. и есть большие сомнения, что dll-вариант окажется кому-то нужным

elf/2
31.01.2006, 15:12
например, чем?
perl/python/javascript или любой другой скриптовый язык. когда/если C++ интерфейс опубликуешь, я могу попробовать...


и есть большие сомнения, что dll-вариант окажется кому-то нужным
если будут методы которые я просил, то как минимум я к фарским плагинам эту dll'ку прикручу

SMT
31.01.2006, 20:15
ты же на с/с++ пишешь плагины? можно и статически слинковать. правда DLL хорош тем, что можно независимо обновлять плагины и плейер

легче всего классы пометить как экспортируемые, чтобы автоэкспортировались функции вроде

?render@SNDRENDER@@QAEIPAUSNDOUT@@IIPATSNDSAMPLE@@ @Z

вместо

public: unsigned int __thiscall SNDRENDER::render(struct SNDOUT *, unsigned int,unsigned int,union SNDSAMPLE *)хотя этот вариант привязывает к компилятору, BC и VC по-разному "заворачивают" типы и параметры методов

вообще-то пока рано делить шкуру неубитого медведя, ещё интерфейс даже не готов. вот теперь думаю, для модуля нужен список свойств, которые можно прочитать, и тех, которые можно редактировать (у VTX-то полно свойст, а у STC всего одно - название песни)

elf/2
01.02.2006, 10:50
ты же на с/с++ пишешь плагины? можно и статически слинковать. правда DLL хорош тем, что можно независимо обновлять плагины и плейер
зришь в корень! кроме того можно иметь одну копию dll'ки в системе и обновлять только ее...


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

вот теперь думаю, для модуля нужен список свойств, которые можно прочитать, и тех, которые можно редактировать
а вот на эту тему хорошо бы с Сергеем Бульбой пошептаться...

boo_boo
02.02.2006, 03:43
отъ xmms-плагин...
раззиповать, сделать "make plugin", скопировать образовавшийся libvtxplay.so в каталог, где xmms держит плагины ввода.
(у меня это /usr/lib/xmms/Input)

кстати, оказывается, есть уже один vtx-xmms-плагин под линух %)
тута: http://sashnov.nm.ru/ayengine.html
и библиотека эмуляции AY/YM там тоже есть

хм, граждане, у которых уши не из зада^H^H^H^H подмышки растут -- как считаете, которая эмуляция больше на железку похожа? :rolleyes:

Sinus
02.02.2006, 13:28
а оно только vtx-ы играет?

boo_boo
02.02.2006, 13:57
а оно только vtx-ы играет?
ну да. вот сделает SMT анонсированный класс Song со всякими разными форматами, будет остальное ;)

Sinus
02.02.2006, 14:33
ну тогда я подожду, ибо в vtx у меня ровно 1 музон ^_~

SMT
14.02.2006, 22:50
времени у меня сейчас не очень, но пока про проект не забыли, буду поддерживать к нему минимальный интерес.
вот прикрутил PT2/PT3 и подготовил интерфейс для чтения/записи свойств муз.файла (пока лишь одна заглушка)

ChipSong поддерживает только методы CreateFromFile и CreatePlayer

ChipPlayer поддерживает play - получение любого нужного количества семплов (есть свой буфер, в котором собираются "лишние" семплы от следующего фрагмента), set_volume, seek, get_pos, get_len

плейер играет vtx, pt2, pt3.
(в принципе, последние сделаны через эмулятор Z80. stc/stp не добавил только потому, что пока не отследил адрес процедурки в плейере, которая зацикливает мелодию)

и это,
в SNDRENDER был глючок! не инициализированы переменные bitA, bitB, bitC, из-за чего звук мог генерироваться "грязным" или со смешением каналов, если объект SNDCHIP создавался в необнулённой памяти (на стеке или в динамической "куче")
замените у себя библиотеку.

насчёт Z80 не знаю, как соберётся под линуксом. попробуйте свой, если не получится unreal'овский

по просьбам некоторых товарищей, работающих в MS Developer Studio, сделан солюшен со всеми проектами (либа и примеры)

Sinus
15.02.2006, 11:43
вечером посмотрю.
я кстати тоже так хотел делать (z80 + sndrender) чтоб pt2/pt3/etc играть.
(наверное самый разумный подход)

boo_boo
16.02.2006, 01:14
насчёт Z80 не знаю, как соберётся под линуксом. попробуйте свой, если не получится unreal'овскийс ходу не собирается, ессно -- ругается на кучу всего, не только в z80. как со временем разгребусь, гляну толком. ...а в MSVC что, нет режима совместимости с ANSI/ISO C++? ;)

SMT
16.02.2006, 07:51
ту мне лог компиляции скинь, посмотрю...

boo_boo
16.02.2006, 11:54
ту мне лог компиляции скинь, посмотрю...вот лог :)

SMT
16.02.2006, 12:43
большая часть из-за неподдержки nameless structs/unions в описании Z80. а так мелочи

boo_boo
16.02.2006, 12:54
большая часть из-за неподдержки nameless structs/unions в описании Z80 ну да, по крайней мере это вроде единственное, что требует вмешательства в код, а не только в декларации.

SMT
16.02.2006, 13:19
не только. ещё проскочила разок переменная, объявленная в for и ещё кое-какие мелочи

SMT
08.03.2006, 23:17
пофиксен глюк с рассинхронизацией AY и других звуковых источников (bepeer, tape, etc), добавлен класс SNDCOUNTER для определения, сколько семплов полностью готово (при генерации от нескольких источников) и откуда из внутреннего буфера надо брать эти семплы. пример использования - в файле sndcounter.h

boo_boo
09.03.2006, 02:16
ура, все работает :)

кстати, предложение -- а почему бы не сделать режим EXTERNAL_BUFFER штатным? то есть передавать в start_frame указатель на буфер и его длину. ИМХО при таком раскладе больше ничего и не надо -- он полностью заменяет нынешний умолчальный режим. а то сейчас чтобы EXTERNAL_BUFFER врубить, приходится лезть в сорцы (тк дефинить его, а потом инклюдить *.h и *.cpp в файл -- неудобно, особенно если такой файл не один ,)

типа: void start_frame(SNDSAMPLE *dst, unsigned dstlen, unsigned dstpos=0);

SMT
09.03.2006, 09:21
кстати, предложение -- а почему бы не сделать режим EXTERNAL_BUFFER штатным?потому что 1) могут передавать размер - не степень двойки и 2) потеряется несколько десятков тактов внутри цикла заполнения буфера из-за переменных вместо констант (действия с константами MSVC оптимизирует на отлично)
сейчас чтобы EXTERNAL_BUFFER врубить, приходится лезть в сорцыпонятно, я специально вынес это в отдельный файл sndbuffer.h - достаточно исправить там 1-2 строки - указать, в какой переменной лежит буфер

з.ы. теперь можно немного упростить обработку звука - start_frame вызывать без параметра, результат end_frame игнорировать (см. пример), объект SNDCOUNTER сам всё считает

boo_boo
09.03.2006, 12:00
потому что 1) могут передавать размер - не степень двойки не степень 2ки и дефайном можно указать :rolleyes:

понятно, я специально вынес это в отдельный файл sndbuffer.h - достаточно исправить там 1-2 строки - указать, в какой переменной лежит буфер тогда еще надо #include "sndcounter.h" в sndcounter.cpp вынести на самый верх, а в sndcounter.h добавить #include "sndbuffer.h" перед ifdef'ом

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

ЗЫ извини за занудство, просто я маньяк по части интерфейсов, когда вижу отличный код, безумно хочется, чтобы и интерфейс был весь из себя :rolleyes:

SMT
09.03.2006, 15:06
не степень 2ки и дефайном можно указатьэто я уже добавил в sndrender.h:
#ifdef SND_EXTERNAL_BUFFER
#if ((SND_EXTERNAL_BUFFER_SIZE & (SND_EXTERNAL_BUFFER_SIZE-1)) != 0)
#pragma error("SND_EXTERNAL_BUFFER_SIZE must be power of 2")
#endif
#endif

тогда еще надо #include "sndcounter.h" в sndcounter.cpp вынести на самый верхсогласен

а в sndcounter.h добавить #include "sndbuffer.h" перед ifdef'омвключается через #include "sndrender.h", который надо вынести наверх

хмм... если важно быстродействие, можно сделать темплейтами с параметрами-константами: медленней не станет, при использовании код править вообще не придется, и если понадобиться с несколькими буферами работать (может пригодиться в плеерах и тп) ничего не помешаетможно, но это надо думать - надо ещё заводить класс-буфер и юзать его как параметр шаблона, что-ли, чтобы все SNDRENDER'ы c одним буфером были одним классом

SMT
09.03.2006, 15:09
не степень 2ки и дефайном можно указатьа хуже того, могут с каждым разом передавать разные буферы и размеры, когда всё должно быть одинаково, чтобы SNDCOUNTER правильно работал

boo_boo
09.03.2006, 19:50
а хуже того, могут с каждым разом передавать разные буферы и размеры, когда всё должно быть одинаково, чтобы SNDCOUNTER правильно работал если указатель на буфер и его размер передавать параметрами темплейта, не смогут... и, кстати, в этом случае ведь как раз и получится один класс на все SNDRENDER'ы, использующие один буфер.

newart
23.07.2008, 23:48
Кто-нибудь знает почему плеер тормозит и как можно от этого избавится?

p.s. Паралельно в окне запускаю игру, AY Emulu хоть бы что, а сабжевый плеер начинает заикаться. :v2_frown:

Да еще и консоль эта не в тему.

Sinus
24.07.2008, 16:06
он не тормозит, просто в AyEmul и в ZXSSK по разному выводится звук.

ZXSSK запихивает звук в несколько звуковых буферов (win, мне проще код написать, чем объяснить как оно работает :) ) или пихает в буфер пока можно (lin), и когда активна другая задача, звук прерывается.

AyEmul либо выставляет большой приоритет звуковому потоку, или генерит звук по требованию ОС (честно говоря не разбирался в этом вопросе), по этому нет разрывов :)

Но знаю одно точно, когда я писал ogg плеер в игрушку, у меня были такие же проблемы как и в ZXSSK, я тогда взял SDL, и написал под него (там как раз не запихивается в буфер пока можно, а вызывается процедура когда надо сгенерировать новые семплы, в принципе в сорсах SDL-а можно посмотреть на реализацию). Факт такой - звук стал ровным и не прерывался больше.

Возьми SDL, перепиши uniplayer под него и потом слушай каков звук.