Автор Тема: конвертация аудио сэмплов и планы на треккер  (Прочитано 5039 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
да, громкость восстанавливается :) засяду теперь за всепеределывание и играть в редакторе будет по человечески :)

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
Sharpnull, еще момент - там нет случаем переключателя PAL или NTSC?

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
SeregaZ, поиск PAL и NTSC по всем файл даёт результат только в vgmwrite.c, который не используется. Но там есть константы для частоты чипов:
#define CLOCK_YM2612 7670454
#define CLOCK_SN76496 3579545
Значит если переставить, то наверно будет PAL:
Цитата
FM sound chip: Yamaha YM2612, clocked at the 68000 clock speed (7.670454 MHz in NTSC, 7.600489 MHz in PAL)
PSG sound chip: Sega PSG (SN76496), clocked at the Z80 clock speed (3.579545 MHz in NTSC, 3.546894 MHz in PAL)
Там ещё просто число в коде есть 7670454, случайно заметил. Ещё есть:
rate = SampleRate = 44100;
rateFMUpdate  = rate / 30;
rateDACUpdate = rate / 60;
// Different rate divisions; rateFMUpdate is how often YM2612 and SN76496 update, and rateDACUpdate is the DAC
Здесь возможно нужно менять на 25 и 50. Также встречаются 60, которые могут быть удобными делителями.
Вам нужен PAL?

Забыл сказать ранее, там же ещё есть режим, который компилируется отдельно:
#ifdef DUAL_SUPPORT
printf("2xYM2612 support enabled.\n");
#endif
Вам такого не надо?

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
про Dual я на форуме моего языка все мозги прокомпосировал :) они так ничего толком не подсказали когда пытался портировать... я так понимаю там просто два ядра? точнее два комплекта по 2 чипа? по идее не надо - ведь на приставке только одна пара чипов - SN9какего там и YM2612. видимо это для особых случаев - помница в какой-то мелодии севенап не хватает каналов для проигрывания всего, что там одновременно играет.

по поводу PAL и NTSC - я фанат PAL. а здесь обратил внимание что чуть быстрее мелодии из Дюны играют вот и решил переспросить - может там какая-то команда для переключения есть. а так уже черновик набросал. доволен до безобразия :) спасибо еще раз.

еще шелу мозги покомпосирую почему сэмплы играют начиная с $30 "ноты", а не с 0 . это мне кажется странным. ведь если всего нот $5F - то $5F - $30 = 47 нот, сиречь сэмплов можно использовать. как-то маловато будет... я думал что можно от 0 до $5F - как количество нот. а так то это вроде не баг, так как шеловский комбайн так собирает. с $30 ноты нулевой сэмпл и дальше. я просто не понимаю логику почему. ведь если с 0 играло бы - больше сэмплов могло бы влезть. странно это.

Добавлено позже:
vgmwrite - это по всей видимости специально ответвление от проигрывателя с целью записей VGM файлов. автор - ValleyBell просто развивает это дело с VGM вот и видимо прикручивал дополнительно запись VGM. это тоже не надо. мне главное чтоб играло правильно, с поддержкой loop - зацикливаний и все модуляции и питчи... то что у меня наколхозено было - половину из этого не играло. только поверхностное представление о мелодии было. теперь же как в аптеке - все четко играет.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
я так понимаю там просто два ядра? точнее два комплекта по 2 чипа?
Инициализируются два YM2612.

Оказалось, что частоты:
#define CLOCK_YM2612 7600489
#define CLOCK_SN76496 3546894
Не влияют на скорость, только на звучание, причём на слух разницы не заметил, только при большем изменении значений.
Но я смог сделать медленнее через изменение (вместо 30 и 60):
// sound.c
rateFMUpdate  = rate / 25;
rateDACUpdate = rate / 50;
// Stream.c
#ifdef WIN32
BUFFERSIZE = SampleRate / 50 * SAMPLESIZE;
Да, второй кусок только для Windows, а для Linux по-другому, там нет константы 60.
Вот DLL с такой скоростью (CLOCK тоже изменил), можно сказать для теста. Если нужно, могу добавить в gemsplay_init() как 5-й параметр.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
а я где-то глюков понасадил... почему-то иногда вылетает. ну это ладно - этот самый YM видимо не совсем правильный. в смысле в оригинальном проигрывателе не совсем точный видимо использован. на эмуляторе (в архиве и 4 банка для проигрывателя и 1 файл ром для запуска в эмуляторе) звучит бочка глухо и коротко. в проигрывателе же какое-то эхо. потом в проигрывателе есть пиликания - не знаю как назвать - в самом начале некие скрипы такие с быстро меняющейся частотой - в эмуляторе такого нет.


Добавлено позже:
ясно. оригинальный код не обрабатывает модуляции :( или это я просто не правильно изначально посылаю модуляции в проигрыватель...

Добавлено позже:
вобщем думаю ошибка при загрузке envelopes.bin в оригинальном проигрывателе. что-то там где не то :)

Добавлено позже:
либо на единицу ошибается при чтении модуляции из этого файла при проигрывании. потому что первая модуляция - 0 по счету - как раз ничего не делает. заглушка.

другой косяк, связанный с модуляциями - что нельзя больше 10 инструкций писать. а там как раз для этого трека одна модуляция на 20 инструкций. но он на это эхо не влияет. просто после 10 инструкции зависает модуляция.
« Последнее редактирование: 25 Март 2020, 07:51:01 от SeregaZ »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
может быть что просто указатель путается и вместо Envelope загружается другой из файлов в оригинальном проигрывателе? вроде где-то здесь в трех местах это происходит.

void SetROMFile(const UINT8* ROMPtr)
{
ROMData = ROMPtr;
PData = ROMPtr;
Tbls.PTBL68K[0] = Tbls.PTBL68K[1] = Tbls.PTBL68K[2] = 0x00;
EData = ROMPtr;
Tbls.ETBL68K[0] = Tbls.ETBL68K[1] = Tbls.ETBL68K[2] = 0x00;
SData = ROMPtr;
Tbls.STBL68K[0] = Tbls.STBL68K[1] = Tbls.STBL68K[2] = 0x00;
DData = ROMPtr;
Tbls.DTBL68K[0] = Tbls.DTBL68K[1] = Tbls.DTBL68K[2] = 0x00;

return;
}

void SetDataFiles(const UINT8* PatPtr, const UINT8* EnvPtr,
  const UINT8* SeqPtr, const UINT8* SmpPtr)
{
ROMData = NULL;
PData = PatPtr;
Tbls.PTBL68K[0] = Tbls.PTBL68K[1] = Tbls.PTBL68K[2] = 0x00;
EData = EnvPtr;
Tbls.ETBL68K[0] = Tbls.ETBL68K[1] = Tbls.ETBL68K[2] = 0x00;
SData = SeqPtr;
Tbls.STBL68K[0] = Tbls.STBL68K[1] = Tbls.STBL68K[2] = 0x00;
DData = SmpPtr;
Tbls.DTBL68K[0] = Tbls.DTBL68K[1] = Tbls.DTBL68K[2] = 0x00;

// Catch NULL-pointers in a way similar to most games.
if (DData == NULL)
DData = NullData;
if (SData == NULL)
SData = DData;
if (EData == NULL)
EData = SData;
if (PData == NULL)
PData = EData;

return;
}

const UINT8* GetDataPtr(UINT8 DataType)
{
if (DataType == 0x00)
return PData + Read24Bit(Tbls.PTBL68K);
else if (DataType == 0x01)
return EData + Read24Bit(Tbls.ETBL68K);
else if (DataType == 0x02)
return SData + Read24Bit(Tbls.STBL68K);
else if (DataType == 0x03)
return DData + Read24Bit(Tbls.DTBL68K);

return NULL;
}

типа EData = SData. то есть в итоге вместо envelope обрабатывается какой-то другой указатель и из-за этого происходит черти чо.

сами модуляции - эти envelope - состоят в банке по следующему алгоритму:
указатель на первую модуляцию - 2 байта
указатель на вторую модуляцию... и так далее по 2 байта указатели.
первая модуляция:
стартовый питч - 2 байта
повторяемый кусок:
значение питч, которое должно прибавляться или убавляться. - 2 байта
счетчик, сколько раз должно это прибавление или убавление на столько-то произойти - 1 байт
(как только в модуляции значение счетчика будет 0 - система понимает, что модуляция закончилась и начинается следующая модуляция. то есть как правило "конец" модуляции это 00 00 00 три нуля в банке модуляций)

известные баги: в оригинальном драйвере есть буфер для модуляции 128 байт. он общий для 4 разных модуляций, которые могут быть запущены одновременно. типа если трек содержит 5 разных модуляций одновременно - одна пойдет лесом. то есть получается по 32 байта на каждую. это не перезаписываемый буфер, как это делает сэмплы например. то есть там как доиграло до конца буфера, но сэмпл занимает больше места, чем буфер - там перезапись и сброс указателя на начало, то есть сэмпл доиграет до конца как полагается. с модуляцией система будет играть до 0 счетчика, либо тупо зависнет после 10 инструкции. то есть 32 байта = 2 байта стартовый питч, 9 * 3 байта инструкции (питч 2 байта и счетчик 1 байт), и в конце три нуля 00 00 00 - тогда все проиграется верно. ежели модуляция имела больше этих 9 инструкций, точнее 10 - ведь 00 00 00 это по сути тоже инструкция, пусть и финализирующая - то модуляция подвиснет к чертовой бабушке. возможно это как раз и происходит, то есть вместо банка модуляций проигрыватель почему-то читает... ээ... скажем банк с мелодиями. там по идее три нуля подряд не встречается, то есть с точки зрения модуляции - конец она не встречает и начинает проигрывать эту "модуляцию" и посему там происходит вакханалия.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
типа EData = SData. то есть в итоге вместо envelope обрабатывается какой-то другой указатель и из-за этого происходит черти чо.
В вашем пример gemstest.zip, равен нулю SmpPtr (семплы) и DData устанавливается в NullData:
static const UINT8 NullData[0x10] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Там есть ошибки в коде может из-за этого. В формате я не разберусь.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
буржуи люди нехорошие... чтоб им всем там икалось.

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

как можно прочитать при старте мелодии содержимое сих моментов?
EnvOfs = Read24Bit(Tbls.ETBL68K) + (EnvNum << 1); // pointer to env table in 68k space
XFER68K(fpoffset, EData, EnvOfs, 2); // read 2 byte offset, into... local fpoffset (shared w/ fetchpatch)
fpoffset_s = Read16Bit(fpoffset);

EnvOfs = Read24Bit(Tbls.ETBL68K) + fpoffset_s; // pointer to env data
EcbBufIdx = EcbPtr[ECBBUFP] & 0x7F;
XFER68K(&ENV0BUF[EcbBufIdx], EData, EnvOfs, 32); // xfer the 32 byte env into this ECB's envelope buffer
в моем недоязыке в нужное место ставлю
Debug EnvOfs
и он мне показывает в окошке текстом значение. есть ли подобное в этом языке программирования?

вот мне не нравится еще EnvNum << 1. может быть там должно было быть + 1, а не сдвиг на 1 байт?

надо посмотреть что в итоге пишется здесь:
XFER68K(&ENV0BUF[EcbBufIdx], EData, EnvOfs, 32);
в память буфера, я так понимаю. то есть получается здесь файл envelope раньше прочитался, втулился куда-то в память. после пошла играть мелодия. там дошло до выбора номера модуляции - 0 номер. она 0 двигает на 1 байт, после пытается прочитать 32 байт в буфер? получается даже если модуляция меньше - все равно 32 прочитает. ну меньше то фиг с ним. вобщем мне в дебаге надо прочитать эти 32 байта в момент запуска модуляции чтоб понять на чтении косяк, или уже при самой обработке. знать бы еще как это делается :)

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
SeregaZ, до вашего сообщения я как раз добавил проект (Project) в это решение (Solution) для компиляции в оригинальный GEMSPlay.exe на основе изменённого кода для DLL, для тестирования.
Добавил на GitHub: https://github.com/infval/GEMSPlay.
После версии v2 + MASTERATN = 0, изменения в настройках проектов, по мелочи и одна ошибка оригинального кода при обработке seqcmd-seqgoto в GemsPlay.c:
case 111: // 111 = goto
//seqgoto:
{
INT16 JmpOfs;
UINT32 FinalAddr;

CurArg = GETSBYTE(ChnCCB, CHBUFPTR); // Исправил CurArg на JmpOfs
JmpOfs = (GETSBYTE(ChnCCB, CHBUFPTR) << 8) | (JmpOfs << 0);
Я оставил замену проигрывателю GEMSPlay - функция main - для тестирования функций библиотеки, если компилировать GEMSPlay (без библиотек), в котором используются gemsplay_init() и т.п. Для переключения замените #if 0 на #if 1 в GEMSPlayLibrary.c:
#if 0
int main(int argc, char* argv[])
какая студия используется? работает ли в ней сразу без ошибок оригинальный код проигрывателя? который не длл, а именно ехе оригинальный. себе поставлю такую-же.
<<< Ликбез по Visual Studio 2019 >>>
Установка
Ставить нужно Visual Studio 2019. В Visual Studio Installer выбрать язык Английский, из "Рабочих нагрузок" "Разработка классических приложений на C++", в "Отдельные компоненты" "Поддержка Windows XP на C++ для инструментов VS 2017".
Работа с проектами
Открывать GEMSPlayLibrary.sln, в Solution Explorer будет 3 проекта: GEMSPlay (оригинальное консольное приложение), GEMSPlayClient (тест библиотеки), GEMSPlayLibrary (библиотека).
Для выбора активного проект (отмечен жирным шрифтом), ПКМ по нему -> Set as Startup Project. При компиляции и запуске (F5/Ctrl+F5) он и будет использован. Для DLL нет смысла, можно просто сделать сборку всего решешения (Build -> Build Solution) или ПКМ -> Build/Rebuild.
Из-за использования одинакового кода для библиотеки и GEMSPlay, входной main() у GEMSPlay в GEMSPlayLibrary.c, также стоит учесть, подсветка синтасиса для макросов препроцессора зависит от того, из какого проекта открыт файл .c/.h (я использовал GEMSPLAY_NO_LIBRARY в GEMSPlay, чтобы убрать предупреждения компилятора).
Настройка проектов
У каждого проекта есть Properties (ПКМ по проекту, хранятся в .vcxproj-файле), где для каждого из Configurantion (Debug/Release) и Platform (Win32/x64) настраиваются доп. библиотеки и другое:
* General > Platform Toolset: v142 - для Win7+, v141_xp - для поддержки XP. Выбрал только для Release/x86 для GEMSPlayClient/Library, так как поиск ошибок IntelliSense (на основе открытых файлов c/cpp/h) не работает из-за этого. Для возвращения на v142 нужно также выбрать Windows SDK Version - 10.0 (latest installed version).
* C/C++ > Code Generation > Runtime Library: влияет на добавление библиотек Visual C++ в exe. Если Debug на конце - для Debug конфигураций, а DLL значит, что не будет включено в exe. Сделал для Release/x86 для GEMSPlayClient/Library.
* Для GEMSPlayLibrary оставил pch.h (Precompiled Header), который был сгенерирован, и использовал C/C++ > Advanced > Forced Include File, чтобы неявно включить pch.h во все .c-файлы. Это можно убрать, по-хорошему туда включают часто используемые неизменяемые библиотеки как windows.h для ускорения компиляции.
* Debugging > Command Arguments: аргументы командной строки при запуске (F5/Ctrl+F5).
* В Solution Properties > Project Dependencies добавил зависимость GEMSPlayClient от GEMSPlayLibrary, чтобы можно было собрать решение, а не по отдельности.
в моем недоязыке в нужное место ставлю
Debug EnvOfs
и он мне показывает в окошке текстом значение. есть ли подобное в этом языке программирования?
Про отладку
Установили аргументы командной строки и запускаете проект в конфигурации Debug с отладкой (F5, а не Ctrl+F5).
Чтобы выполнение остановилось, ставите breakpoint нажатием на область слева от номера строки кода. Можно делать шаги по строкам, как обычно.
Чтобы увидеть значение переменной, вводите её имя в панели Watch 1 внизу, во вкладках Auto и Locals отображаются соответствующие переменные на данный момент. Можно выводить в консоль через printf() или OutputDebugString() выводить в специальное окно, но там не строка форматирования (для решения этой проблемы смотрите ответы: How do I print to the debug output window in a Win32 app?).
« Последнее редактирование: 28 Март 2020, 21:18:06 от Sharpnull »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
надо добавить ремарку об адресах для множества игр, которые можно проигрывать с помощью этой программы от товарища Megaplex  http://elektropage.ru/forum/7-68-3#2624 нажать на кнопку спойлер.

и по всей видимости какое-то обновление оригинала было в прошлом году, но оно не решает этой проблемы с модуляцией. я так понимаю там правилась какая-то команда в банке с секвенциями.

по поводу студии - официальная ссыль шлет меня в пешее эротическое путешествие. попробую на торрентах.




Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
надо добавить ремарку об адресах для множества игр
Куда добавить?
и по всей видимости какое-то обновление оригинала было в прошлом году, но оно не решает этой проблемы с модуляцией. я так понимаю там правилась какая-то команда в банке с секвенциями.
Изменение в GemsPlay.c из вашего файла только в:
if (Read24Bit(SAMP.PTR) > 0x20000) // [not in actual code - >512 KB]
SAMP.FIRST = 0;
// Стало
if (Read24Bit(SAMP.PTR) > 0x200000) // [not in actual code - >512 KB]
SAMP.FIRST = 0;
Больше ничего нового не было? Изменить в коде?
по поводу студии - официальная ссыль шлет меня в пешее эротическое путешествие.
Странно, здесь https://visualstudio.microsoft.com/ru/vs/ нажимаете Community 2019.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
в комментарии к проекту наверное. либо скопировать оттуда весь лист с адресами и добавить в текстовом файле, чтоб можно было использовать если кому надо, чтоб не искать самим адреса. там просто почти все GEMS игры. я оттуда для своей онлайновой базы адреса брал для распаковки мелодий.

по поводу ссылки - я наверное там и качал. 70 метров установщик скачивает. после крутит и крутит и крутит, потом нет связи с сервером :)

по поводу изменений кода - видимо ошибка при копировании? кажись строчки одинаковые...


Добавлено позже:
так. на старом компе с ХР осталась 6.0 студия. там без танцев с бубном открылся оригинал. и даже собирается ехе файл. буду искать косяк в нем. вдруг повезет... дур... эээ... новичкам везет. так что надеюсь найдется эта причина корявого воспроизведения.
« Последнее редактирование: 28 Март 2020, 21:45:44 от SeregaZ »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
либо скопировать оттуда весь лист с адресами и добавить в текстовом файле
Можно или выложит отдельно (в gist.github) и дать ссылку в wiki на github, или в саму wiki добавить. Я ещё находил рипы https://hcs64.com/mboard/forum.php?showthread=52626&lastpage и там в My GEMS Rips.7z тоже есть список для 791 игр/ромов, по вашей ссылке меньше. Придётся сравнить и поискать актуальный список.
кажись строчки одинаковые...
Было 0x20000 (128КБ) стало 0x200000 (2МБ).
70 метров установщик скачивает. после крутит и крутит и крутит, потом нет связи с сервером
Стоит попробовать ещё раз позже. Я сегодня обновлял до новой версии, проблем не было.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
эх. не помогло. в этом участке, по всей видимости, все верно. с горем пополам втулил туда запись файла и скидывание что там оно в буфер пишет. оказалось то что надо. значит надо искать в DOENVELOPE
// DOENVELOPE - update the pitch envelope processor
static void DOENVELOPE(void)
{
UINT8* CurECB; // Register IX
UINT8 TestRes;
UINT32 SegPos; // Register HL
UINT8 SegCntr; // Register A
UINT16 SegVal;
UINT8* CurPB; // Register IY

CurECB = ECB; // point at the envelope control blocks
//envloop:
while(1)
{
DACxME();
if (CurECB[ECBCHAN] & 0x80) // end of list? [BIT #7]
break; // yup - return
if (! (CurECB[ECBCHAN] & 0x40)) // active ? [BIT #6]
{
//envactive: // check if this envelope's timebase has ticked

if (TBASEFLAGS & 0x20) // sfx timebase? [BIT #5]
//envsfx:
TestRes = (TBASEFLAGS & 0x01); // yes - check sfx tick flag [BIT #0]
else
TestRes = (TBASEFLAGS & 0x02); // no - check music tick flag [BIT #1]
if (TestRes)
{
//envticked:
if (CurECB[ECBCTR] == 0) // ctr at 0?
{
//envnextseg: // yes - [Note: The comment is really cut here.]
SegPos = (CurECB[ECBPTRH] << 8) | (CurECB[ECBPTRL] << 0);
SegPos -= 0x1E80; // [1E80 is subtracted to make up for ENV0BUF[]]
SegCntr = ENV0BUF[SegPos];
if (SegCntr == 0)
{
// jr envdone
TestRes = 0x00;
}
else
{
SegPos ++;
CurECB[ECBDELL] = ENV0BUF[SegPos];
SegPos ++;
CurECB[ECBDELH] = ENV0BUF[SegPos]; // ECB's delta <- this segment's delta
SegPos ++;
DACxME();
SegPos += 0x1E80; // [not in actual code, SegPos is relative to ENV0BUF here]
CurECB[ECBPTRL] = (SegPos & 0x00FF) >> 0;
CurECB[ECBPTRH] = (SegPos & 0xFF00) >> 8;
// [fall through to envseg]
}
}
else // no - process segment
{
SegCntr = CurECB[ECBCTR] - 1;
}
if (TestRes) // [need to check that, since envdone skips envseg]
{
//envseg:
CurPB = &PBTBL[CurECB[ECBCHAN] & ~0x20]; // ptr to this channel's pitchbend entries [RES #5]
CurECB[ECBCTR] = SegCntr;
SegVal = (CurPB[PBEBH] << 8) | (CurPB[PBEBL] << 0);
SegVal += (CurECB[ECBDELH] << 8) | (CurECB[ECBDELL] << 0);
CurPB[PBEBL] = (SegVal & 0x00FF) >> 0;
CurPB[PBEBH] = (SegVal & 0xFF00) >> 8;
// [fall through to envneedupd]
}
else
{
//envdone:
CurPB = &PBTBL[CurECB[ECBCHAN] & ~0x20]; // ptr to this channel's pitchbend entries [RES #5]
CurPB[PBEBL] = 0; // zero the envelope bend on this channel
CurPB[PBEBH] = 0;
CurECB[ECBCHAN] = 0x40; // shut off this envelope
//jr envneedupd
}
//envneedupd:
CurPB[PBRETRIG] |= 0x01; // [SET #0]
NEEDBEND = 1;
//jr envnext
}
}
//envnext: // nope - loop
CurECB ++;
}

return;
}

но здесь я вобще не понимаю что происходит :) как в эту функцию попадает содержимое буфера? то есть те 32 байта что пишутся здесь:
XFER68K(&ENV0BUF[EcbBufIdx], EData, EnvOfs, 32);

и со структурой файла мальца ошибся. там сначала идет счетчик - 1byte, а потом значение на какое надо изменять значение частоты ноты - 2 byte, тип .w, это который от минус 32 тыщ скок там до плюс 32 тыщ сколько там.

я так полагаю что эта DOENVELOPE вызывается тыщи раз, а уже внутри проверятся - а тикнул ли 1 единица времени BPM? то есть темпа. если тикнул, то должны происходить изменения частоты играющей ноты. скажем оно при старте было изначально частота 100. в файле модуляции стоит 5 счетчик и значение -10 к примеру. значит нота стартовала как 100, после наступил тик тэмпа и по этой инструкции 100 + (-10) = 90, а сам счетчик 5 - 1 = 4. нота понизилась по частоте. дальше пока не тикнет следующий тик тэмпа. станет 90 + (-10) = 80, счетчик 4 - 1 = 3.
если счетчик стал 0, то надо передвинутся на следующую инструкцию и прочитать новое значение счетчика и новое изменение частоты. а если счетчик уже 0, значит модуляция закончилась. плюс еще тут должна быть проверка на канал - в каком канале это должно происходить.

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

Добавлено позже:
неужели бох ValleyBell услышал мои молитвы? :)))

Here is a .diff for the source code that fixes the bug. (It's in the function VTANDET.)
--- GemsPlay_2019-06-16.c   2019-06-16 17:35:28.000000000 +0200
+++ GemsPlay.c   2020-03-28 19:37:16.000000000 +0100
@@ -2908,7 +2908,7 @@
   
    DACxME();
   
-   if (ChnCCB[CCBFLAGS] & 0x20)   // envelope retrigger on?
+   if (ChnCCB[CCBFLAGS] & 0x40)   // envelope retrigger on? [BIT #6]
    {
       // yes - trigger the envelope
       TRIGENV(ChnCCB, noteon.ch, ChnCCB[CCBENV]);

опять ничерта не понимаю что тут происходит... и где. это поможет?
« Последнее редактирование: 28 Март 2020, 23:35:19 от SeregaZ »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
опять ничерта не понимаю что тут происходит... и где. это поможет?
Да, это исправляет ошибку. Забавно, что я случайно нашёл этот баг, когда сравнивал asm-код, а тут уже решено.
bit 6,(IX+CCBFLAGS) ; envelope retrigger on?
ret Z
push BC ; yes - trigger the envelope
ld C,(IX+CCBENV)
ld E,B
call TRIGENV
Нужно было 6-й бит выставлять if (ChnCCB[CCBFLAGS] & 0x40).
Странно, что сам автор не выложил у себя на https://github.com/ValleyBell/.
Обновил https://github.com/infval/GEMSPlay, добавил также if (Read24Bit(SAMP.PTR) > 0x2000000), сделал GEMSPlay тоже совместимым с XP в Release/x86, жирненькие получились файлы.
Скомпилированные файлы здесь https://github.com/infval/GEMSPlay/releases. Нумерация версий своя, считал с 1.0.0, поэтому 1.0.3.

Ещё можно повысить точность, обновив fm2612 и sn76489, но вряд ли будет заметна разница.
В сравнении с https://github.com/mamedev/mame/blob/master/src/devices/sound/fm2612.cpp
У функций TimerAOver и TimerBOver:
  ST->TAC += (1024-ST->TA);
  ST->TAC = (1024-ST->TA);
У update_phase_lfo_slot и update_phase_lfo_channel
  был косяк int kc = (blk<<2) | opn_fktable[fn >> 7];
  ValleyBell исправил int kc = (blk<<2) | opn_fktable[fn >> 8];
  но у MAME теперь int kc = (blk<<2) | opn_fktable[(fn >> 7) & 0xf];
И в этих функциях есть различия: ym2612_update_one, ym2612_write.

https://github.com/ValleyBell/libvgm/blob/master/emu/cores/sn76489.c
Здесь немного SN76489_Update

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
насчет YM2612 возможно есть чуть разночтений - так как в эмуляторе звук соник танка звучит по одному, здесь чуть по другому. это специальный Ch3mode режим, когда у третьего канала чипа YM2612 используются дополнительные частоты для "ноты". но он так редко используется, что думаю фиг с ним :)

еще отдельной строкой хочу сказать спасибо за ссыль с кучей банков. я тоже оттуда добавляю те, которых у меня не было. там правда совсем упоротые буржуи собирали абсолютно все что есть. всякие промежуточные релизы, беты, даже по датам сборки... извращенцы. но вот качество банков хромает. из тех, какие я добавляю в базу - бывает что банки чуть недорезанные. у игры про муравья B.O.B. банк инструментов по моему недовырезан из рома. там не хватает сколько-то инструментов. у супермена, не помню уже точно но по моему он - вовсе отсутствует банк с модуляциями. Fury как-то там Paws Fury чтоль - этот вовсе не хочет распаковываться. видимо там дикий кастом драйвера, что на стандартной козе к нему не подъедешь. так-же не все будет проигрываться верно опять таки из-за этого самого кастома - MK3 - по идее проигрыватель не сможет корректно проигрывать сэмплы. потому что там DPCM. Comix Zone и Ooze - там еще хуже - ADPCM, но хорошо хоть не на всех сэмплах, а только частично. аркадный рестлинг или как он там - там как у МК3, Punisher по моему тоже как у МК3. Zero Tolerance и Flashback - будут иметь только мелодии в банках, без спецэффектов. но уже десяток из этого архива я примерно распаковал и добавлю в базу :)  приятный бонус. сам редактор еще буду допиливать. у меня проигрывается из кучи разных мест. везде нужно будет заменить механизм на этот новый из библиотеки. радости полные штаны. спасибо.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
видимо будет еще обновление... я надеюсь. отписал ему, что есть вылет. что-то флаги сэмплов не нравятся этому коду. понятно что стандартно там обычно $45 скажем. 4 означает 8 бит по моему и тип байтов толи .а толи .b - скорей всего .b от -127 до +127, а 5 это номер в таблице частот 10400. а тут-же какой-то $75... и система несколько впадает в ступор из-за этого :) я вот не знаю что могут означать эти флаги, акромя 4. там должно быть еще 4 битный какой-то из флагов. это я знаю точно. но какой и какие все остальные - тут черт знает.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
SeregaZ, нашёл место, где возможно проблема. Мне ещё CppCheck подсказывал, что здесь "мёртвый код":
SmplPtr += SmplLeft; // SAMPLEPTR <- SAMPLEPTR + 128Потому что SmplPtr больше не используется. Если написать SAMPLECTR += SmplLeft; или SAMPLECTR += 128;, то не вылетает (в первом случае SmplLeft равен 113, когда ловлю эту строчку). ASM-код не помог. Напишите им там. Вот сборка с первым вариантом.
--------
Сравнил на слух с треком отсюда: https://www.zophar.net/music/sega-mega-drive-genesis/nightmare-circus через foobar2000 + Game Emu Player. Звук заметно отличается.
« Последнее редактирование: 31 Март 2020, 06:35:32 от Sharpnull »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
тут заметил такую вещь в этой фиксенной версии - песня стартанула, доиграло вступительное пилим пилим - потом заиграл сэмпл... а я беру и жму еще раз ентер - то есть рестарт мелодии, но звук сэмпла продолжается, но песня то начала играть сначала - там по идее не должен играть сэмпл в начале. получается перезапуск мелодии "помнит" старый сэмпл и проигрывает его дальше. причем тыркая и тыркая ентер - этот звук так и продолжается :)

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

Добавлено позже:
и по моему это сэмпл хора. там голоса должны петь ноту. здесь в новой версии по моему звучит гораздо ниже. такое ощущение что флаг частоты теперь вместо 5 - скажем 6. то есть вместо 10.4khz стало играть 8.6khz чтоль... или что-то такое.
« Последнее редактирование: 31 Март 2020, 07:16:12 от SeregaZ »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
я вроде теперь начал понимать зачем этот loop нужен в сэмплах. это повторение кусочка сэмпла.
// SmpFlags:
// Bits 0-3: Sample Rate (based on YM2612 Timer A)
// Bit  4: Looping on/off
// Bit  7: 4-bit PCM mode (already handled by DumpDACSounds)

то есть Bit  4:   Looping on/off включает, а параметр loop в хедере сэмпла видимо размер откуда начать проигрывать.

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

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

Добавлено позже:
то есть сейчас начинает играть первый сэмпл нормально, потом должен быть луп - но он заикается в этом моменте - после идет второй сэмпл, завершающий. он играет нормально. возможно этот параметр loop - не правильно прочитан.

Добавлено позже:
а может быть что этот SmplLeft это на самом деле значение loop из хедера?
RAW 'sample_5D.snd'
FLAGS =$75
SKIP  =$0000
FIRST =$1F8F
LOOP  =$0FEF
END   =$0005

тогда это имело бы смысл SmplPtr += SmplLeft; - то есть указатель сэмпла сдвигался на значение $0FEF - видимо куда-то в середину сэмпла и потом уже играл в рипите оттуда на всю длительность, что отведена. точнее не SmplPtr, а что там другое значение?
« Последнее редактирование: 31 Март 2020, 07:36:51 от SeregaZ »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
получается перезапуск мелодии "помнит" старый сэмпл и проигрывает его дальше.
Если каждый раз вызывать gemsplay_init(), то проблемы нет. Похоже нашёл ещё баг с битом, но это не решает проблему.
if (ChnCCB[CCBFLAGS] & 0x40) // running? [BIT #4]должно быть
if (ChnCCB[CCBFLAGS] & 0x10) // running? [BIT #4]Это в CLIPALL, который вызывается  во время остановки.
и это наша dll вылетала, кстати. а оригинальный ехе - зацикливался, то есть начинал играть вступление, доходило до сэмпла, после сбрасывался на начало. и так до бесконечности, но вылета не было.
Потому что там обращение к чужой памяти, может повезти или нет, зависит от сборки.
а может быть что этот SmplLeft это на самом деле значение loop из хедера?
Похоже на то, если заменить на:
SAMPLECTR += SAMP.LOOP;То идёт повтор, но есть щелчки между. По ASM-коду это кажется не сходится. Кстати, SAMP.END не используется в коде вообще.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
почти не слышно этих щелчков. может как раз SAMP.END и должен вычитаться, чтобы в момент лупов оно не доигрывало до конца? я вот не знаю вобще для чего этот END нужен. ждать пока буржуйский товарищ ответит... прошлый раз он несколько дней отвечал :(

Добавлено позже:
я думаю в момент писанины кода ValleyBell просто не имел под рукой подобных примеров - как прошлый раз с retrigger 1 командой, как сейчас с лупами в сэмпле и черт знает каким флагом в параметре. поэтому косяки и повылазили :)
« Последнее редактирование: 31 Март 2020, 08:51:10 от SeregaZ »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
SeregaZ, я ещё раз сравнил код с ASM, добавил две строчки по аналогии, но звук такой же как в последнем тесте.
SmplPtr = Read24Bit(SAMPLEPTR);
SmplPtr += SmplLeft; // add to sample pointer
SmplPtr -= SAMP.LOOP; // then subtract loop length
Write24Bit(SAMPLEPTR, SmplPtr); // store new (beginning of loop ptr)
SAMPLECTR = SAMP.LOOP; // !!! ДОБАВИЛ !!!

SmplLeft = 128 - SmplLeft; // BC <- number to complete this 128byte bank
if (! SmplLeft)
    return; // none to xfer

SAMPLECTR -= SmplLeft; // subtract these few samples from ctr
SmplPtr = Read24Bit(SAMPLEPTR);
XFER68K(DACFIFO + DstAddr, DData, SmplPtr, SmplLeft); // reload FIFO

SmplPtr += SmplLeft; // SAMPLEPTR <- SAMPLEPTR + 128
Write24Bit(SAMPLEPTR, SmplPtr); // !!! ДОБАВИЛ !!!
В ASM первые 5 строк выше это:
ld HL,(SAMPLEPTR)
ld A,(SAMPLEPTR+2)
push BC
zadd HL,BC
adc A,0 ; add to sample pointer
ld BC,(SAMPLOOP)
scf
ccf
sbc HL,BC
sbc A,0 ; then subtract loop length
ld (SAMPLEPTR),HL ; store new (beginning of loop ptr)
ld (SAMPLEPTR+2),A
ld (SAMPLECTR),BC
BC точно равен SAMPLOOP, но это "ld (SAMPLECTR),BC" ("SAMPLECTR = SAMP.LOOP;") было пропущено. Последние 5 строчек:
ld HL,(SAMPLECTR)
scf
ccf
sbc HL,BC ; subtract these few samples from ctr
ld (SAMPLECTR),HL
                ; DE still hangin out where it left off
ld HL,(SAMPLEPTR) ; HL <- src addr lsw
ld A,(SAMPLEPTR+2) ; A <- src addr msb
push BC
call XFER68K ; reload FIFO
pop BC

ld HL,(SAMPLEPTR)
ld A,(SAMPLEPTR+2)
zadd HL,BC
adc A,0
ld (SAMPLEPTR),HL
ld (SAMPLEPTR+2),A ; SAMPLEPTR <- SAMPLEPTR + 128
Здесь явно пропущен Write24Bit(SAMPLEPTR, SmplPtr);. С ним чуть менее заметны "щелчки/шумы".
В прошлый тест SAMPLECTR += SAMP.LOOP; сработало по случайности, код получился похожим за исключением небольшого смещения у SAMPLECTR.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
r57shell сказал:
насколько я помню как-то так
<skip><first><end>
   <----loop>

как-то он не очень помог :)

с другой стороны:
реальный размер сэмпла: 8084
FIRST =$1F8F = 8079
END   =$0005   8084 - 8079 = 5

значит пойду попробывать склеить по этой инструкции и послушать результат. чтобы понять откуда надо считать луп - от конца физического сэмпла или от -5 от конца (или от начала). и доигрывать в лупе - до конца физического сэмпла или до этой -5 точки.

Добавлено позже:
чот не особо помогло... в смысле так-то не щелкает конечно, но куда девать этот end так и не понятно :) что с ним что без него - вроде не щелкает. но это склейка сэмпла в вакууме. как там на самом деле должно происходить - черт знает... но у меня еще два варианта в голове. первый - записать во Fusion, после распотрошить VGM и вытащить оттуда сэмпл. по идее он будет единым целым и после побайтно посмотреть где склейка. второй вариант - записать сэмпл со словами один два три, вручную примерно набросать параметры skip, first, loop и end на примерные размеры и смотреть как оно будет выглядеть в итоге. в идеале надо сделать чтоб слово один - 1 раз, два - пять раз в лупе и в конце 3 один раз. хотя это не логично, так как система не может знать что время звучания заканчивается и пора подставлять последнюю часть end. именно поэтому закрывает звучание сэмпла здесь в этой песне - второй сэмпл.

пока-что примерно так:
  FIRST = $1F8F  ;  8079
  LOOP  = $0FEF  ;  4079
  S_END = $0005
  LOOPSize = (FIRST - LOOP) - S_END ; (этот S_END не нужно видимо или он где-то в другом месте должен быть)

  counter = 10
  newmemsize = FIRST + (LOOPSize * counter)
  NewMEM = AllocateMemory(newmemsize)
  If NewMEM
    CopyMemory(CodeSamplesArr(1)\image, NewMEM, CodeSamplesArr(1)\size)
   
    For i = 1 To counter
      ;                 сдвиг откуда копировать   расчет куда копировать
      CopyMemory(CodeSamplesArr(1)\image + LOOP, NewMEM + (LOOPSize * i), LOOPSize)
    Next

  EndIf

но это как бы цельный единый большой кусок памяти и поэтому может играет без щелчков. в GEMS помница буфер для сэмпла и он поделен на 2 куска. скажем буфер 20 байт по 10 байт половинки (размер от фонаря. естественно там больше буфер, но я не знаю сколько) сэмпл скажем 100 байт. получается он пишет первые 10 байт в первый кусочек и играет их. после проверяет - есть ли еще байты - есть - пишет следующие 10 во второй кусок. играет. проверяет есть ли еще - есть - пишет в первый кусочек, а указатель в конце второго куска прыгает обратно на начало первого куска буфера. и так как мигалка он пишет и играет.

еще момент - а могли появится эти щелчки из-за модификации кода под PAL?

пойду искать где старый код по потрошению VGM. я точно такое делал... весь вопрос где он остался...

Добавлено позже:
итак. правильно получается так:
SKIP  =$0000
FIRST =$1F8F
LOOP  =$0FEF
END   =$0005
сначала играется FIRST
вычисляем место, откуда будет читаться луп: FIRST + (FIRST - LOOP)
из этого места читаем фрагмент на длину LOOP  = $0FEF и этот кусочек дописываем в конец сэмпла...
и так в конец дописывается и дописывается все время, пока длится duration.

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

а последних 5 байт физического файла сэмпла, указанных в END, тут не видать вовсе.

Добавлено позже:
это еще формула не учитывает SKIP. с ним еще потом тоже надо будет разобраться как именно он пропускает и чего пропускает...

Добавлено позже:
так. скип это сколько байт будет пропущено в физическом сэемпле.
типа физически сэмпл имеет 100 байт
SKIP = 10
FIRST = 85
LOOP = 20
END = 5
указатель проигрывания = указатель на физ сэмпл + SKIP
проигрывать от "указатель проигрывания" на длину FIRST
адрес лупа в физическом сэмпле = указатель на физ сэмпл + SKIP + (FIRST - LOOP)
repeat
 как только проигрывание достигает "указатель на физ сэмпл" + SKIP + FIRST, то дописывать в конец инфу на размер LOOP начиная с адреса "адрес лупа в физическом сэмпле"
until duration не кончилось
« Последнее редактирование: 31 Март 2020, 19:57:20 от SeregaZ »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
конвертация аудио сэмплов и планы на треккер
« Ответ #55 : 03 Апрель 2020, 06:36:30 »
Похоже исправил. Данные сэмплов переносятся в Z80 (функция XFER68K) по 128 байт, когда счётчик подходит к 0, то сначала записываются оставшиеся, а после ещё до 128 байтов от начала LOOP, если есть. Для 2-й записи нужно было сместить указатель (DstAddr += SmplLeft;) куда записывать, иначе начало LOOP записывалось поверх записанного конца. Отсюда и "щелчки" - оставшийся мусор из DACFIFO, который равен 256 байтам.
Остался "щелчок" после проигрывания куска. Что делать с END непонятно.
Протестируйте и я залью код.
еще момент - а могли появится эти щелчки из-за модификации кода под PAL?
Я не добавлял ничего связанного с PAL. Это было только в сборке GEMSPlayLibrary_50Hz для теста, мне показалось, что вам это не нужно.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов и планы на треккер
« Ответ #56 : 03 Апрель 2020, 07:07:44 »
SKIP FIRST LOOP END
SKIP - пропуск. не играет эту часть сэмпла. указатель по идее сдвигается на значение SKIP
FIRST - то что должно проиграть. либо от начала сэмпла либо отступив от начала SKIP если он есть.
LOOP - в случае когда доигрался FIRST до конца, то надо примерно так расчитать указатель откуда начать читать на длину LOOP:
FIRST + (FIRST - LOOP). хотя шелл говорит надо от конца отнимать это значение... но суть таж самая :) точнее еще учесть SKIP надо в формуле
SKIP + FIRST + (FIRST - LOOP) = это мы узнаем фрагмент сэмпла, который в LOOP, и который получается будет проигрываться на репите, пока идет звучание сэмпла - то есть время duration из "мелодии".
END - получается то что не играется совсем. ни в лупах ни в оригинальном сэмпле. конечно по логике вещей проще было бы выбросить из сэмпла это значение байтов и тем самым сэкономив память в роме. но тут видимо фишка в том, что может быть несколько заголовков на один и тот-же сэмпл. просто скажем частота меняется. или в другом случае сэмпла надо проиграть полностью. поэтому если есть значение END - этот фрагмент от конца сэмпла не играется.

у меня щелкает :) хотя мож я не то чото тестирую... еще поковыряю.

у меня вопрос по поводу буфера - он точно один на 128 байт размером? не два по 64? типа вначале дописывает 64 в первый, играет. как приближается к концу - дописывает следующие 64 во второй, играет... как приближается к концу - записывает следующие 64 из сэмпла в первые 64 байта, играет... ну и потом остаток - там играет не все 64, а столько сколько осталось... соответственно и дописывает к тому значению, сколько осталось loop. просто если 128 один буфер - может быть такое, что оно еще играет, скажем на 120 байте играет, а тут пора уже обновлять буфер... но ведь оно еще не доиграло. а если доигрывать до конца, и потом дописывать - не будет ли щелчка?

Добавлено позже:
а хотя у меня-же не верно банк составляет. да да, у меня ж там ошибка. ща исправлю скажу щелкает или нет.

Добавлено позже:
gemsplay_stop по всей видимости не стопарит проигрывание такого сэмпла в loop :))))
« Последнее редактирование: 03 Апрель 2020, 07:16:49 от SeregaZ »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов и планы на треккер
« Ответ #57 : 03 Апрель 2020, 07:34:19 »
Цитата
Остался "щелчок" после проигрывания куска.
не слышу вроде бы... хотя это может дорожка не та опять таки... я там вырезал вобще все для тестов и остался только сэмпл, чтоб слушать как он склеивает.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
конвертация аудио сэмплов и планы на треккер
« Ответ #58 : 03 Апрель 2020, 07:52:27 »
По коду: SKIP один раз добавляется к указателю PTR, также один раз используется FIRST (SAMPLECTR = SAMP.FIRST;, где SAMPLECTR - количество байт для вывода, после чего может произойти LOOP back, тогда SAMPLECTR = SAMP.LOOP). Остальные ваши формулы я не понимаю, там скорее FIRST - LOOP и SKIP + FIRST - LOOP. В любом случае вроде всё правильно, кроме END.
у меня вопрос по поводу буфера - он точно один на 128 байт размером?
// FILLDACFIFO - gets the next 128 bytes of sample from the 68000 into the DACFIFO
static void FILLDACFIFO(UINT8 ForceFill)
:) Там DACFIFO на 256 байт, эти 128 байт записываются попеременно. Так что можно сказать два по 128.
gemsplay_stop по всей видимости не стопарит проигрывание такого сэмпла в loop :))))
Ну да, я же копировал реализацию из команд с клавиатуры. Можно очистить память вместо этого и снова инициализировать.
я там вырезал вобще все для тестов и остался только сэмпл, чтоб слушать как он склеивает.
В архиве одинаковые файлы в двух папках. Я тестировал на вашем прошлом forum.zip, там несколько раз повторяется этот кусок, так вот между ними есть "щелчок", но не те, которые между LOOP. В этих я тоже не слышу.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов и планы на треккер
« Ответ #59 : 03 Апрель 2020, 08:04:17 »
а я опять торопился видимо не то в архив засунул...

по поводу стопа - попробую.

Добавлено позже:
не получается. вылетает с ошибкой... а как можно в gemsplay номер трека указать? я к чему - для проигрывания можно два трека создавать. первый тот что выбран для проигрывания, а второй - там будет проигрывание сэмпла, который на самом деле 0 байт. то есть стоп будет работать как плей трек номер 2. но там 0 байт для сэмпла и тогда этот loop будет выключаться.

Добавлено позже:
сранно... в одном месте ставлю - работает. в другом месте программы ставлю - вылетает с ошибкой :)

Добавлено позже:
« Последнее редактирование: 03 Апрель 2020, 12:02:18 от SeregaZ »