Разработка и ромхакинг > Ромхакинг и программирование
конвертация аудио сэмплов и планы на треккер
<< < (3/6) > >>
SeregaZ:
надо добавить ремарку об адресах для множества игр, которые можно проигрывать с помощью этой программы от товарища Megaplex  http://elektropage.ru/forum/7-68-3#2624 нажать на кнопку спойлер.

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

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



Sharpnull:

--- Цитата: SeregaZ от 28 Март 2020, 21:17:28 ---надо добавить ремарку об адресах для множества игр
--- Конец цитаты ---
Куда добавить?

--- Цитата: SeregaZ от 28 Март 2020, 21:17:28 ---и по всей видимости какое-то обновление оригинала было в прошлом году, но оно не решает этой проблемы с модуляцией. я так понимаю там правилась какая-то команда в банке с секвенциями.
--- Конец цитаты ---
Изменение в 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;
--- Конец кода ---
Больше ничего нового не было? Изменить в коде?

--- Цитата: SeregaZ от 28 Март 2020, 21:17:28 ---по поводу студии - официальная ссыль шлет меня в пешее эротическое путешествие.
--- Конец цитаты ---
Странно, здесь https://visualstudio.microsoft.com/ru/vs/ нажимаете Community 2019.
SeregaZ:
в комментарии к проекту наверное. либо скопировать оттуда весь лист с адресами и добавить в текстовом файле, чтоб можно было использовать если кому надо, чтоб не искать самим адреса. там просто почти все GEMS игры. я оттуда для своей онлайновой базы адреса брал для распаковки мелодий.

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

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


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

--- Цитата: SeregaZ от 28 Март 2020, 21:32:41 ---либо скопировать оттуда весь лист с адресами и добавить в текстовом файле
--- Конец цитаты ---
Можно или выложит отдельно (в gist.github) и дать ссылку в wiki на github, или в саму wiki добавить. Я ещё находил рипы https://hcs64.com/mboard/forum.php?showthread=52626&lastpage и там в My GEMS Rips.7z тоже есть список для 791 игр/ромов, по вашей ссылке меньше. Придётся сравнить и поискать актуальный список.

--- Цитата: SeregaZ от 28 Март 2020, 21:32:41 ---кажись строчки одинаковые...
--- Конец цитаты ---
Было 0x20000 (128КБ) стало 0x200000 (2МБ).
--- Цитата: SeregaZ от 28 Март 2020, 21:32:41 ---70 метров установщик скачивает. после крутит и крутит и крутит, потом нет связи с сервером
--- Конец цитаты ---
Стоит попробовать ещё раз позже. Я сегодня обновлял до новой версии, проблем не было.
SeregaZ:
эх. не помогло. в этом участке, по всей видимости, все верно. с горем пополам втулил туда запись файла и скидывание что там оно в буфер пишет. оказалось то что надо. значит надо искать в 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]);
--- Конец кода ---

опять ничерта не понимаю что тут происходит... и где. это поможет?
Sharpnull:

--- Цитата: SeregaZ от 28 Март 2020, 23:28:39 ---опять ничерта не понимаю что тут происходит... и где. это поможет?
--- Конец цитаты ---
Да, это исправляет ошибку. Забавно, что я случайно нашёл этот баг, когда сравнивал 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:
насчет YM2612 возможно есть чуть разночтений - так как в эмуляторе звук соник танка звучит по одному, здесь чуть по другому. это специальный Ch3mode режим, когда у третьего канала чипа YM2612 используются дополнительные частоты для "ноты". но он так редко используется, что думаю фиг с ним :)

еще отдельной строкой хочу сказать спасибо за ссыль с кучей банков. я тоже оттуда добавляю те, которых у меня не было. там правда совсем упоротые буржуи собирали абсолютно все что есть. всякие промежуточные релизы, беты, даже по датам сборки... извращенцы. но вот качество банков хромает. из тех, какие я добавляю в базу - бывает что банки чуть недорезанные. у игры про муравья B.O.B. банк инструментов по моему недовырезан из рома. там не хватает сколько-то инструментов. у супермена, не помню уже точно но по моему он - вовсе отсутствует банк с модуляциями. Fury как-то там Paws Fury чтоль - этот вовсе не хочет распаковываться. видимо там дикий кастом драйвера, что на стандартной козе к нему не подъедешь. так-же не все будет проигрываться верно опять таки из-за этого самого кастома - MK3 - по идее проигрыватель не сможет корректно проигрывать сэмплы. потому что там DPCM. Comix Zone и Ooze - там еще хуже - ADPCM, но хорошо хоть не на всех сэмплах, а только частично. аркадный рестлинг или как он там - там как у МК3, Punisher по моему тоже как у МК3. Zero Tolerance и Flashback - будут иметь только мелодии в банках, без спецэффектов. но уже десяток из этого архива я примерно распаковал и добавлю в базу :)  приятный бонус. сам редактор еще буду допиливать. у меня проигрывается из кучи разных мест. везде нужно будет заменить механизм на этот новый из библиотеки. радости полные штаны. спасибо.
SeregaZ:
видимо будет еще обновление... я надеюсь. отписал ему, что есть вылет. что-то флаги сэмплов не нравятся этому коду. понятно что стандартно там обычно $45 скажем. 4 означает 8 бит по моему и тип байтов толи .а толи .b - скорей всего .b от -127 до +127, а 5 это номер в таблице частот 10400. а тут-же какой-то $75... и система несколько впадает в ступор из-за этого :) я вот не знаю что могут означать эти флаги, акромя 4. там должно быть еще 4 битный какой-то из флагов. это я знаю точно. но какой и какие все остальные - тут черт знает.
Sharpnull:
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. Звук заметно отличается.
SeregaZ:
тут заметил такую вещь в этой фиксенной версии - песня стартанула, доиграло вступительное пилим пилим - потом заиграл сэмпл... а я беру и жму еще раз ентер - то есть рестарт мелодии, но звук сэмпла продолжается, но песня то начала играть сначала - там по идее не должен играть сэмпл в начале. получается перезапуск мелодии "помнит" старый сэмпл и проигрывает его дальше. причем тыркая и тыркая ентер - этот звук так и продолжается :)

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

Добавлено позже:
и по моему это сэмпл хора. там голоса должны петь ноту. здесь в новой версии по моему звучит гораздо ниже. такое ощущение что флаг частоты теперь вместо 5 - скажем 6. то есть вместо 10.4khz стало играть 8.6khz чтоль... или что-то такое.
SeregaZ:
я вроде теперь начал понимать зачем этот 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, а что там другое значение?
Sharpnull:

--- Цитата: SeregaZ от 31 Март 2020, 07:06:40 ---получается перезапуск мелодии "помнит" старый сэмпл и проигрывает его дальше.
--- Конец цитаты ---
Если каждый раз вызывать gemsplay_init(), то проблемы нет. Похоже нашёл ещё баг с битом, но это не решает проблему.

--- Код: ---if (ChnCCB[CCBFLAGS] & 0x40) // running? [BIT #4]
--- Конец кода ---
должно быть

--- Код: ---if (ChnCCB[CCBFLAGS] & 0x10) // running? [BIT #4]
--- Конец кода ---
Это в CLIPALL, который вызывается  во время остановки.
--- Цитата: SeregaZ от 31 Март 2020, 07:06:40 ---и это наша dll вылетала, кстати. а оригинальный ехе - зацикливался, то есть начинал играть вступление, доходило до сэмпла, после сбрасывался на начало. и так до бесконечности, но вылета не было.
--- Конец цитаты ---
Потому что там обращение к чужой памяти, может повезти или нет, зависит от сборки.

--- Цитата: SeregaZ от 31 Март 2020, 07:25:06 ---а может быть что этот SmplLeft это на самом деле значение loop из хедера?
--- Конец цитаты ---
Похоже на то, если заменить на:

--- Код: ---SAMPLECTR += SAMP.LOOP;
--- Конец кода ---
То идёт повтор, но есть щелчки между. По ASM-коду это кажется не сходится. Кстати, SAMP.END не используется в коде вообще.
SeregaZ:
почти не слышно этих щелчков. может как раз SAMP.END и должен вычитаться, чтобы в момент лупов оно не доигрывало до конца? я вот не знаю вобще для чего этот END нужен. ждать пока буржуйский товарищ ответит... прошлый раз он несколько дней отвечал :(

Добавлено позже:
я думаю в момент писанины кода ValleyBell просто не имел под рукой подобных примеров - как прошлый раз с retrigger 1 командой, как сейчас с лупами в сэмпле и черт знает каким флагом в параметре. поэтому косяки и повылазили :)
Sharpnull:
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:
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 не кончилось
Sharpnull:
Похоже исправил. Данные сэмплов переносятся в Z80 (функция XFER68K) по 128 байт, когда счётчик подходит к 0, то сначала записываются оставшиеся, а после ещё до 128 байтов от начала LOOP, если есть. Для 2-й записи нужно было сместить указатель (DstAddr += SmplLeft;) куда записывать, иначе начало LOOP записывалось поверх записанного конца. Отсюда и "щелчки" - оставшийся мусор из DACFIFO, который равен 256 байтам.
Остался "щелчок" после проигрывания куска. Что делать с END непонятно.
Протестируйте и я залью код.

--- Цитата: SeregaZ от 31 Март 2020, 17:16:47 ---еще момент - а могли появится эти щелчки из-за модификации кода под PAL?
--- Конец цитаты ---
Я не добавлял ничего связанного с PAL. Это было только в сборке GEMSPlayLibrary_50Hz для теста, мне показалось, что вам это не нужно.
SeregaZ:
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 :))))
SeregaZ:

--- Цитата ---Остался "щелчок" после проигрывания куска.
--- Конец цитаты ---
не слышу вроде бы... хотя это может дорожка не та опять таки... я там вырезал вобще все для тестов и остался только сэмпл, чтоб слушать как он склеивает.
Sharpnull:
По коду: SKIP один раз добавляется к указателю PTR, также один раз используется FIRST (SAMPLECTR = SAMP.FIRST;, где SAMPLECTR - количество байт для вывода, после чего может произойти LOOP back, тогда SAMPLECTR = SAMP.LOOP). Остальные ваши формулы я не понимаю, там скорее FIRST - LOOP и SKIP + FIRST - LOOP. В любом случае вроде всё правильно, кроме END.

--- Цитата: SeregaZ от 03 Апрель 2020, 07:07:44 ---у меня вопрос по поводу буфера - он точно один на 128 байт размером?
--- Конец цитаты ---

--- Код: ---// FILLDACFIFO - gets the next 128 bytes of sample from the 68000 into the DACFIFO
static void FILLDACFIFO(UINT8 ForceFill)
--- Конец кода ---
:) Там DACFIFO на 256 байт, эти 128 байт записываются попеременно. Так что можно сказать два по 128.

--- Цитата: SeregaZ от 03 Апрель 2020, 07:07:44 ---gemsplay_stop по всей видимости не стопарит проигрывание такого сэмпла в loop :))))
--- Конец цитаты ---
Ну да, я же копировал реализацию из команд с клавиатуры. Можно очистить память вместо этого и снова инициализировать.
--- Цитата: SeregaZ от 03 Апрель 2020, 07:34:19 ---я там вырезал вобще все для тестов и остался только сэмпл, чтоб слушать как он склеивает.
--- Конец цитаты ---
В архиве одинаковые файлы в двух папках. Я тестировал на вашем прошлом forum.zip, там несколько раз повторяется этот кусок, так вот между ними есть "щелчок", но не те, которые между LOOP. В этих я тоже не слышу.
SeregaZ:
а я опять торопился видимо не то в архив засунул...

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

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

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

Добавлено позже:
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии