| Разработка и ромхакинг > Ромхакинг и программирование |
| конвертация аудио сэмплов и планы на треккер |
| << < (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 будет выключаться. Добавлено позже: сранно... в одном месте ставлю - работает. в другом месте программы ставлю - вылетает с ошибкой :) Добавлено позже: |
| Навигация |
| Главная страница сообщений |
| Следующая страница |
| Предыдущая страница |