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

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

Оффлайн SeregaZ

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

посему у меня два вопроса:
1. может ли кто посодействовать с перепиливанием кода оригинала SoX, чтобы оно из приложения превратилось в одиночную дллку, и получается могла работать с памятью? типа подсунул образ файла оригинала из памяти - оно результат родило тут-же память. тут-же из памяти проиграл, послушал, устроило - сохранил, создался файл. не понравилось - закрыл, память просто очистилась и все как раньше было, без всяких промежуточных сохранений на жесткий диск.
https://sourceforge.net/p/sox/code/ci/master/tree/ понятия не имею что это за язык.
2. о самой нормализации - по идее, в самом начале я родил алгоритм ресэмплинга из высосокачественной вавки в мои целевые 10.2к, правда я весьма посредственно представлял что там должно было происходить... и результат был, как бы мне сойдет, но я не уверен что это был правильный результат :) посему забил, и вернулся к bass.dll. так я к чему - может быть есть какой-то алгоритм, какие-то правила для этой самой нормализации... то есть моя вавка - это мульон значений от -127 до +127. может мне просто в цикле нужно производить какие-то операции с этими значениями и в итоге этот самый SoX нафиг не нужен будет? ну и в каком месте следует производить эту нормализацию? с оригинальной высококачественной вавкой и после конвертировать в 10.2к, или можно сначала конвертировать в 10.2к и уже после производить эту нормализацию? просто с 10.2к данных будет в разы меньше :) а высококачественная вавка - там надо будет сначала определить в каком формате данные, стерео или моно... гемороя больше. не говоря что это может быть ogg файл. в случае bass.dll ему все фиолетово для конвертации что wav что 16 бит, что 24, что ogg - результат мне предоставит 8bit mono PCM 10.2. проще связываться с уже конверченным результатом и что-то там нормализировать, но правильнее думаю все-таки с высококачественной вавкой творить свои дела, и уже потом конвертировать - ведь там данных больше.

так уж получилось что хочу всего и сразу :) честно говоря в своем редакторе уже сам начинаю путаться где и что... посему для вставки сэмплов в игру хотелось бы прикрутить сии прибамбасы, чтоб сэмплы стали красивше, а не так как сейчас. и причем чтоб все однокликово, хотя я понимаю что однокликово не получится, что лучше заранее подготовить сэмплы в крутых аудио редакторах, и только потом импортировать... но просто такими редакторами пользоваться умеют не все и посему для таких людей, которые не знают всякие монстры аудиоредактирования - хотелось бы подстелить соломки, создав такой однокликовый функционал.
« Последнее редактирование: 29 Декабрь 2019, 14:31:19 от SeregaZ »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #1 : 19 Декабрь 2019, 16:06:32 »
1. может ли кто посодействовать с перепиливанием кода оригинала SoX, чтобы оно из приложения превратилось в одиночную дллку, и получается могла работать с памятью?
http://sox.sourceforge.net/Docs/FAQ:
Цитата
8. Is SoX's functionality also available as a function library?
Yes, the source code for SoX contains both SoX, the application, and libSoX. LibSoX is a static library that can be used in other applications. It contains routines such as sox_open_read(), sox_open_write(), sox_read(), sox_write(), and sox_close() to allow reading and writing audio files.

Further information can be found in the libSoX manual page (though it is somewhat out of date) and in the examples supplied in the SoX source-code distribution.
Хотя там написано про статическую компиляцию, по докам понятно, что компиляция как динамическая библиотека возможна.

Различаться громкость между bass.dll и SoX может быть из-за параметров, в SoX можно указать dB-level (кажется тоже самое, что опция "Нормализовать пик амплитуд до" в нормализации в Audacity). В Audacity ещё есть опция "Убрать смещения по оси амплитуды и выровнять по отметке 0.0". Лучше вам конечно разобраться как работает нормализация и понять почему такой разный результат.
--------
Лучше конечно поискать алгоритм, если он не очень сложный. Целую библиотеку подключать только из-за нормализация слишком жирно.
« Последнее редактирование: 19 Декабрь 2019, 17:42:18 от Sharpnull »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #2 : 19 Декабрь 2019, 17:55:43 »
так никто и не знает :) отмалчиваются как партизаны... так то знать бы чего куда прибавлять\убавлять и фиг бы с ним.

но с этим SoX все-же лучше. там в командной строке надо добавлять параметр norm и нормализует так сказать. а громкость это gain - её я не трогаю. что интересно после нормализации если были "заскоки" - как они там clips по научному? он пишет в консоли об этом, дескать может потом убавите громкость чуть чуть? мне впрочем и с этими клипсами пойдет. что интересно в случае с bass.dll там маленько съедает звук С при конвертации - становится шипение вместо чистой С, как если бы по тарелке на барабанах стучать hi-hat которая. в случае с SoX такого вроде нет. звук "С" остается большее нормальным, чем басовский "Ш".

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #3 : 19 Декабрь 2019, 18:43:19 »
так никто и не знает :) отмалчиваются как партизаны
Чего не знают? Как добавить библиотеку SoX в программу я указал. По 2-му вопросу, убрав всё воду: вы хотите алгоритм нормализации. Ну так курите код SoX или других библиотек. За вас никто не будет гадать почему там тихо, а там нет.

Сделать хорошо по умолчанию всё равно не получится. Придётся добавить опцию "нормализация" и по-хорошему другие настройки.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #4 : 19 Декабрь 2019, 18:54:45 »
алгоритм не знают и молчат. а по поводу шерстения кода - так этож совсем не мой язык так сказать. я даж не в курсе в какой среде это нужно собирать. это то еще проклятье чужой код пытаться завести... как сто тыщь ошибок вылезет. то синтаксис не тот, то файла какого не хватает... знаю я какой это геморой. эх... печаль тоска и безобразие. пойду погуглю чем статическая от динамической библиотеки отличается.

Добавлено позже:
похоже дллкой не получится. там прицелом тыщу других длл. получается они все в корневой папке болтаться должны. в смысле рядом с ехе файлом. так как перенеся в другую папку при попытке импорта этой длл - он ругается, что подружек не видит. хотя они рядышком лежат. отдельная же ехешка такой проблемы иметь не будет. лежит себе в отдельной папке и лежит. но вот неудобство будет писать во временный файл. при работе в памяти было бы солиднее, и только итоговый результат чтоб сохранять как юзверь благославит, то есть ему понравилось. сейчас будет сохранять в любом случае. печалька.
« Последнее редактирование: 19 Декабрь 2019, 22:02:54 от SeregaZ »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #5 : 19 Декабрь 2019, 23:58:52 »
вобщем теперь из редактора весь суп набор SoX будет распаковываться в папку рядом. потом по требованию сувать туда сэмпл, SoX его конвертит и ложит рядышком. редактор ждет, пока конвертер закончит, берет этот файл, загружает и дальше по накатанной. результат главно позитивный, а вот метод гавно. я доволен :)

Оффлайн megavolt85

  • Пользователь
  • Сообщений: 1464
  • Пол: Мужской
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #6 : 20 Декабрь 2019, 01:18:03 »
похоже дллкой не получится. там прицелом тыщу других длл. получается они все в корневой папке болтаться должны. в смысле рядом с ехе файлом.

ох батенька, да вы винды не знаете  :) она гадкая ищет DLL либо в папке с EXE'хой, либо в system32

так этож совсем не мой язык так сказать.

пардон, а на каком языке пишешь что православный СИ не узнаёшь?

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #7 : 20 Декабрь 2019, 01:28:55 »
у меня древнеславянский - PureBasic. от этой идеи по использованию dll пришлось отказаться. во первых синтаксис как правильно импортировать функции, а так-же порядок их применения. а второе - главный минус в том, что эта библиотека требует тыщу еще других. получается если я её буду в своем ехе файле вызывать, то надо обязательно чтоб они рядышком валялись. это не преемлимо. итак я там уже насорил так сказать... а тут еще десяток лепить, да еще со всякими матерными названиями. поплевался, да делать нечего... засунул их всех в ехешку, а когда моя ехе запускается она сразу и установщик и само приложение - если нет библиотек рядышком в отдельной папке - то создает и распаковывает туда. после уже оттуда ехе файл в скрытом режиме запускается и конвертит. потом моя программа забирает файл и дальше использует. в своей же программе запилил меню с тремя вариантами загрузки: старый с bass.dll, потом этот новый с SoX как есть, и третий SoX с нормализацией. и сэмплы стали получше :) мои старые ваще ничерта не слыхать и приходилось FM звук делать потише, чтобы сэмплы не тонули. а с этой нормализацией прям нормально так вышло. результатом доволен, а вот метод, повторюсь - гавно :)

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #8 : 20 Декабрь 2019, 06:20:27 »
SeregaZ, жаль, что C не знаете. Параметр --norm равносилен gain -n. В исходном коде gain в src/gain.c, там же "эмулируется" старый --norm. Чтобы вычленить алгоритм нужно убирать условия типа if (p->do_balance || p->do_balance_no_clip) {, которые не используются и задаются другими параметрами, переместить макросы, понять когда вызываются create, start, flow, drain, stop функции и т. п.

Здесь даются ссылки на библиотеки (тоже C) нормализации с реализацией вроде попроще и там же пример совсем простой пиковой нормализации в пару строк, которая не учитывает человеческий слух, но и проблем с клиппингом нет. Возможно её вы и пробовали сами реализовать. В sox/src/synth.c есть другая реализация такой нормализации:
double min, max;
int j;
for (j = 0, min = max = 0; j < buffer_len; ++j) {
    min = min(min, buffer[j]);
    max = max(max, buffer[j]);
}

for (j = 0; j < buffer_len; ++j) {
    buffer[j] = (2 * buffer[j] - max - min) / (max - min);
}
На вход buffer с положительными вещественными значениями, а на выходе от -1.0 до 1.0. Для 16-bit WAV (или сырых данных) значения допустим от 0 до 65535 (или [-32767(8), 32767] приводите к этому добавив 32767 или 32768), после [-1.0, 1.0] умножаете на 32767 или (value + 1.0) / 2.0 * 65535. Про граничные значения не знаю.

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

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #9 : 20 Декабрь 2019, 11:33:29 »
это то понятно, что даже голос одной и той-же мадамы в разных сэмплах будет отнормализирован по разному. ведь там разные фразы, разные топовые пики, следовательно громкость будет разной. по идее все фразы надо чтоб были в одном сэмпле, а после нормализации резать. тогда все будут одинаковые по громкости. функционал по резке я добавлял. а вот длительность у меня маленькая - максимум 10 секунд. туда могут не уместится все фразы за раз. ну пока так как есть. дальше посмотрю когда дойдет дело. пока спал додумал что сделал несколько не верно :) всегда пишет в 10.2к, но ведь исходные сэмплы могут быть меньше. если для Дюны пофиг и можно все поголовно 10.2 фигачить, то для Зомбей там максимум 7+ сколько-то, так как вроде драйвер там старый используется. этот момент надо будет предусмотреть.

Оффлайн Segaman

  • Пользователь
  • Сообщений: 3240
  • Пол: Мужской
  • Blast Processing!
    • Youtube
    • Просмотр профиля
Re: конвертация аудио сэмплов
« Ответ #10 : 23 Декабрь 2019, 10:32:02 »
почитал тему.
непонял почему неиспользовать goldwave например.
все эти танцы с бубном больше времени вашего потратят, чем если пользоваться тем, что уже до вас написано и хорошо отлажено.
хотя дело может быть в том, что я не понял сути

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #11 : 23 Декабрь 2019, 16:20:54 »
объяснение зачем :) с примерами!


Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #12 : 23 Декабрь 2019, 17:04:10 »
SeregaZ, про goldwave можно было просто написать, что вам нужно программно делать.
Почему вы пишите везде 10.2 КГц, а в программе 10400 Гц написано?

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #13 : 23 Декабрь 2019, 17:15:34 »
а... эм... чото вот втемяшилось что 10.2... даааааа... надо исправить на 10.4 :)

;10.4/8.7/7.3/6.5/5.8/5.2 - frequency FLAGS
; 5  /6  /7  /8  /9  /A
« Последнее редактирование: 23 Декабрь 2019, 17:23:37 от SeregaZ »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #14 : 27 Декабрь 2019, 18:08:44 »
тем временем я окончательно вынес мозг на форуме bass.dll товарищу Ian и в итоге теперь нормализацию (увеличение громкости) редактор сэмплов может делать и с помощью bass.


вот теперь дилемма - откручивать ли обратно SoX? :) из-за него редактор раздулся до 10 мегабайт... из-за него будет создаваться дополнительная папка в папке с редактором, и из-за него будут создаваться временные файлы конвертации на жестком диске в количестве 1 штука.

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

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
конвертация аудио сэмплов
« Ответ #15 : 27 Декабрь 2019, 19:34:22 »
вот теперь дилемма - откручивать ли обратно SoX?
Конечно убирать, вы делаете для ленивых, им всё равно, а кому надо будет разбираться в параметрах специальных программ.
Лучше бы написали, как добились этого: правильный параметр/готовка или своя реализация? С примером кода.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
Re: конвертация аудио сэмплов
« Ответ #16 : 27 Декабрь 2019, 19:46:17 »
с использованием функционала bass.dll. тот буржуйский товарищ все разжувал, и все неправильные мои места поправил :)

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

Добавлено позже:
Procedure EncodeCallback(handle.i, channel.a, *buffer, length.i, *user)
 
  Define Rec=#True
 
  CopyMemory(*buffer, *MemStore + EncSampleSize, length) ; *MemStore - тоже глобальный кусочек памяти
  EncSampleSize + length
 
  ProcedureReturn Rec
 
EndProcedure

                      ; global value
                       EncSampleSize = 0
                       
                       ;// Create a decoding channel from the source file
                       ; *SoundData - образ входного файла в памяти, SampSize - размер этого сэмпла в памяти
                       Decoder = BASS_StreamCreateFile(#True, *SoundData, 0, SampSize, #BASS_STREAM_DECODE)
                       BASS_ChannelSetAttribute(Decoder, #BASS_ATTRIB_SRC, 6);
                       
                       If SEMenuEvent = #WavImportLoad4 ; в моем случае это другой пункт меню. если без нормализации просто пропустить
                       ; Normalization requires an additional pass to get the current level.
                       ; You can use BASS_ChannelGetLevelEx in that.
                       SElevel.f
                       SEpeak.f
                       Repeat
                         result = BASS_ChannelGetLevelEx(Decoder, @SElevel, 1, #BASS_LEVEL_MONO);
                         If SElevel
                           ; if any value exist
                           If (SEpeak < SElevel) : SEpeak = SElevel : EndIf
                         EndIf
                       Until result = 0 ; repeat until SElevel = 0. end of playing?
                       
                       ; You can then use the BASS_FX_VOLUME effect To normalize the level
                       ; based on that "peak" reading, like this:
                       SEvolfx = BASS_ChannelSetFX(Decoder, #BASS_FX_VOLUME, 0)
                       SEparam.BASS_FX_VOLUME_PARAM
                       SEparam\fTarget = 1.0 / SEpeak
                       SEparam\fTime = 0;
                       BASS_FXSetParameters(SEvolfx, SEparam);
                       
                       ; Then rewind the decoder (BASS_ChannelSetPosition With pos=0) And do your conversion.
                       BASS_ChannelSetPosition(Decoder, 0, #BASS_POS_BYTE)                       
                       EndIf
                       
                       ;// Create a mixer To change the sample rate To 10.4 kHz RecOutputFrequency
                       Mixer   = BASS_Mixer_StreamCreate(RecOutputFrequency, 1, #BASS_STREAM_DECODE|#BASS_SAMPLE_8BITS|#BASS_MIXER_END)
                       
                       ;// Add the decoder To the mixer  As a channel
                       BASS_Mixer_StreamAddChannel(Mixer, Decoder, #BASS_MIXER_DOWNMIX);
                       
                       ; memory for 10 sec sample
                       *MemStore = AllocateMemory(104000)
                       
                       ;// Set a WAV writer on it |#BASS_ENCODE_NOHEAD
                       BASS_Encode_Start(Mixer, #Null, #BASS_ENCODE_PCM|#BASS_ENCODE_NOHEAD, @EncodeCallback(), #NUL)
                       
                       ; wait, until convert happen:
                       While (BASS_ChannelIsActive(Decoder) = #BASS_ACTIVE_PLAYING)
                         BASS_ChannelGetData(Mixer, @Buf, SizeOf(Buf));
                       Wend

« Последнее редактирование: 27 Декабрь 2019, 19:53:28 от SeregaZ »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
конвертация аудио сэмплов и планы на треккер
« Ответ #17 : 29 Декабрь 2019, 14:56:59 »
как известно я люблю что-то начинать ваять... и забрасывать на половине. вот сейчас хочу начать делать недоGEMS треккер, чтобы можно было визуально править какие-то нюансы. то есть абы какой конвертер из Дефлемаска в ГЕМС я запилил, и с мелодиями без извращений результат вполне себе... однако весь затык с использованием как раз извращений в Дефлемаске - всяких слайдов для нот. сии приблуды в конвертере весьма поверхностны и неточны. и поэтому думаю надо сделать что-то типа дополнительного редактора для правки подобных случаев.

использовать буду не GEMS напрямую как оно есть - то есть 4 файла банков, а распакованный вариант .code файл с кучей всяких .raw файлов и прочих, что рожает r57shell'овский комбайн при распаковке банков GEMS. что-то типа такого:
SECTION CODE
channel_0:
 loop $7F
 delay 0
 nop
 mastervolume 4
 tempo 120
 delay 192
 pitch $0000
 delay 27
 patch patch_0C
 delay 0
 volume 12
 duration 3
 delay 24
 note $52
 note $51
 delay 48
...

с синтаксисом что есть что в этих строчках все понятно и даже у меня что-то там умеет проигрывать (опять таки не очень точно). весь затык в том, как это все удобно организовать :) хотелось бы конечно как в дефлемаске, но тут есть несколько глобальных различий. если дефлемаск, скажем в первом канале имеет 100 строчек, то и во втором 100. и в третьем 100 и в 10 тоже 100. то в GEMS каждый канал может иметь свое количество строчек (строчка это я имею ввиду одну единицу делея - задержки между событиями), а во вторых в GEMS может быть до 16 каналов - в дефлемаске только 10, и то строго первые 6 FM, потом 3 PSG тональный и 1 PSG шумовой. в GEMS любой вариант типа инструмента FM или PSG может быть в любой дорожке.

предварительно набросал примерно так:


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

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

Оффлайн SeregaZ

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

For ( ; VTblPtr[VTBLFLAGS] != 0xFF; VTblPtr += 7)
что там происходит - черт знает :) я понимаю если у For есть переменная, которая изменяется. есть стартовое значение для переменной - например 0 и есть конечное - скажем 5. есть параметр Step - шаг. типа если поставить шаг 2, то цикл с 0 до 5 будет крутится так: 0, 2, 4, конец. но здеееесь? For, и первым параметром точка с запятой... шта?!?!? а после еще != это что? неравно?

или вот здесь:
PSGVTBLTG3(VTBLFLAGS) &= ~0x20амперсанд равно и значок герца. буржуи "объяснили" it is a binary and of the inverted $20. мне как-то помогло слабо... хоть и честно скопипастил оттуда уже переведенную конструкцию. я хоть и изобрел свой любимый метод: если не понимаешь код, то просто верь - но здесь уже перебор.


вобщем я к чему веду... тут у нас на форуме тыщу специалистов по С :) может хоть один сможет помочь в одном геройском деле по спасению вселенной? есть исходник GEMS проигрывателя от товарища ValleyBell'a - я его пытался конвертировать в свой язык. но не выходит... перенес структуры, глобальные переменные, начал функции и утоп в непонятках. так вот может ли кто поглядеть и пересобрать этот исходник, вместо консольного ехешника сделать одиночную dll, которую можно импортировать в проект и где будут три "внешние" команды: посылка 4 поинтеров памяти в библиотеку (это адреса памяти GEMS банков - сэмплы, инструменты, модуляции и ноты мелодий), плей и стоп. предполагается что посылаться для проигрывания всегда будет одна мелодия (или спецэффект). впрочем наверное надо еще некий GEMSinit еще вывести. типа чтоб очередность была:
GEMSinit (для инициализации. видимо оно нужно будет перед каждым запуском новой мелодии. для сброса так сказать. и это еще большой вопрос предусмотрен ли сброс данных в этом коде. ведь в оригинале консольная программа запускается один раз с одним комплектом банков GEMS)
послать 4 указателя (и видимо размеры памяти этих указателей. что-то типа GEMSSetSamples(pointer*, size), GEMSSetEnvelopes(pointer*, size) и так далее всего 4 банка)
GEMSPlay - всегда первая мелодия играет (нулевая видимо, так как с 0 начинается)
GEMSStop

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

так что есливчто - оставляю ссыль на архив:
https://www.dropbox.com/s/zt86m73g6a65dn4/SEGA.zip?dl=1

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
SeregaZ,
for ( ; VTblPtr[VTBLFLAGS] != 0xFF; VTblPtr += 7)Си-шный оператор for простой. for (начальное_действие; условие_продолжения; выполнить_после_каждой_итерации). Каждое из 3 выражений можно опустить вплоть до бесконечного цикла (for (;;)), выражения могут быть любыми. Это вы могли бы легко изучить. В данном примере цикл выполняется пока байт из массива не равен 0xFF, а VTblPtr += 7 - переход на следующие 7 байтов. Было бы попроще написать: for (int i = 0; VTblPtr[i + VTBLFLAGS] != 0xFF; i += 7).
PSGVTBLTG3(VTBLFLAGS) &= ~0x20В коде написано:
PSGVTBLTG3[VTBLFLAGS] &= ~0x20; // yes - clear locked bit in TG3Там уже объяснение, что снимается бит. Действительно, обычно так и снимают биты. Можно записать как unsigned char n = 0; n = n & (~0x20); где ~ инвертирует все биты (~0x20 = 0xDF (для однобайтовой переменной)), а & - побитовое И.

Посмотрел код, там есть инициализация и очищение. Всё ли очищает - трудно сказать. Запутано из-за использования разных слоёв абстракций (init от одного, воспроизведение от другого) и есть лишняя команда gems_loop(), которая вызывается до инициализации, что меня удивило (если убрать, всё работает, но может она нужна).

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
где ~ инвертирует все биты (~0x20 = 0xDF (для однобайтовой переменной)), а & - побитовое И.
не помогло :) три раза перечитал... мои три класса церковно приходской не дают осилить сей глубокомысленный момент программирования на С. я больше как бы практикой знакомлюсь с языком (своим, не С) и в этой самой практике я не встречал и просто не понимаю зачем может понадобится подобное инвертирование бит. зеркалирование - вот да :) это понимаю. а инвертирование... как-то не вижу такой задачи где оно нужно. но в целом замысел этого инвертирования как бы понял. из всяких 1010 делать 0101. про & тоже вроде понятно. своего рода обрезка значения в нужных пределах.

Добавлено позже:
про loop ничего не скажу. в архиве только один пример. может в каком-то другом случае вылезет боком. тоже посмотрел - функция большая. раз большая - наверное важная :))) хотя не вижу где она вызывается. в объявлениях есть, сама функция есть. а в init она просто упомянута в комментарии в конце функции:
Цитата
   //loop:
   // [see gems_loop]
но тут я не советчик... в архиве еще asm файлы есть с родным GEMS как он на приставке работает. но там я понимаю еще меньше того малого что понимаю в С. но может там какой ответ на этот животрепещущий вопрос есть. хотя не вижу я там loop... или вижу, но не различаю...
« Последнее редактирование: 23 Март 2020, 06:35:30 от SeregaZ »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
SeregaZ, сделал библиотеку, не очень хорошо, но работает.
В папке Release: dll, lib и GEMSPlayClient.exe, которая тестирует dll (запускать GEMSPlayClient.bat как у вас).
Заголовочный файл GEMSPlayLibrary.h, функции такие:
// Инициализация. Указатели на массивы из байтов: patches, envelopes, sequences, samples.
// Возвращает 1 - если получилось инициализировать и есть хотя бы одна последовательность, иначе 0. (int в VC++ - 4 байта)
// Размер не передаётся в оригинале, видимо как-то определяется конец.
// Каждый вызов будет очистка gemsplay_cleanup(), если не было.
int gemsplay_init(
const unsigned char* PatPtr, const unsigned char* EnvPtr,
const unsigned char* SeqPtr, const unsigned char* SmpPtr);
// Очистка выделенной памяти.
void gemsplay_cleanup(void);// Остановка.
void gemsplay_stop(void);// Переключать паузы.
void gemsplay_pause(void);// Воспроизведение. Повторный вызов начнёт воспроизведение сначала.
void gemsplay_play(void);
GEMSPlayClient.exe принимает только 4 аргумента, начинается воспроизведение, Enter, пауза, Enter, продолжается воспроизведение, Enter, выход.

Не разобрался что такое song, sequences и т. п., в GEMSPlay.exe есть всякие настройки воспроизведения, я оставил значения по умолчанию.
Я не использовал статическую компоновку в dll и GEMSPlayClient.exe, поэтому требуется распространяемый компонент Microsoft Visual C++ для Visual Studio 2015, 2017 и 2019 (как вариант).
Надеюсь вам не надо поддерживать WinXP.
Попробуйте библиотеку и отпишитесь.

Оффлайн SeregaZ

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

по поводу статической компоновки - это я не понимаю, так-же как и обязательное наличие: распространяемый компонент Microsoft Visual C++ для Visual Studio 2015, 2017 и 2019. и Windows XP по идее нужна. предполагалось что работать редактор будет везде, на любом компьютере. лишь бы 1024х768 разрешение экрана было, иначе не все элементы интерфейса будут видны. гордость в том то и состоит что не требуются всяких нетфреймворков и прочего. просто это как-то глупо, что для редактирования игры из 90 требуется дополнительно установить софт из 2020 какогонить.

Добавлено позже:
если производить эти операции 2 раза, то все работает. на третий происходит вылет:
GEMSStop() ; стоп мелодии, если играла на момент загрузки другого комплекта банков
GEMSCleanup() ; очистка
GEMSInit(*GEMSPatches, *GEMSEnvelopes, *GEMSSequences, *GEMSSamples) ; инициализация с новыми данными
« Последнее редактирование: 23 Март 2020, 23:30:13 от SeregaZ »

Оффлайн SeregaZ

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

Добавлено позже:
оригинальный ехе этот набор банков проигрывает нормально, с сэмплами.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
поет :) но на счет возврата 1 если есть хоть одна "мелодия" в банках есть - видимо что-то не то... так как GEMSInit(0, 0, 0, 0) возвращает единицу. по идее раз 0 в секвенциях - значит здесь точно нет треков и по идее должно было вернуть 0 в качестве результата работы функции.
Действительно, эта ошибка из оригинальной программы, там в LoadSongList() предполагается, что GetDataPtr(0x02); может вернуть NULL и тогда будет seq_count = 0, но, на самом деле, если все NULL передать (GEMSInit(0, 0, 0, 0)), то будет нулевая последовательность. Значит возвращается 0 только если не сработал sound_init().
просто это как-то глупо, что для редактирования игры из 90 требуется дополнительно установить софт из 2020 какогонить.
Это нормально. Нужно либо компилировать в VC6++ (ужас), либо включать в каждую dll и exe исполняемые библиотеки, что увеличивает размер файлов и потребление RAM, хоть и не большое.
Windows XP по идее нужна. предполагалось что работать редактор будет везде, на любом компьютере
Надеюсь поддержку Win98 не предполагаете. :) Вот статическая компоновка и поддержка WinXP, только не забудьте проверить на ней.
оригинальный ехе этот набор банков проигрывает нормально, с сэмплами.
Мой exe и/или GEMSPlay.exe? Всё зря?
UPD: Да в моей версии какая-то ошибка, попробую разобраться.

Добавлено позже:
если производить эти операции 2 раза, то все работает. на третий происходит вылет:
Это ещё не проверял.

Добавлено позже:
Ошибку с сэмплами нашёл, опечатка из-за которой просто не копировались сэмплы. С вылетом после нескольких вызовов ещё не нашёл, когда найду, то выложу обновлённую версию.
« Последнее редактирование: 24 Март 2020, 00:20:30 от Sharpnull »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
Исправил ошибку с повторным вызовов, как раз была из-за gems_loop(), который вызывался до sound_init(), о чём я писал ранее. Возможно там что-то ещё нужно инициализировать заново, это уже зависит от правильности инициализации.
Обновил GEMSPlayClient, теперь он 4 раза производит действия (паузы и очистка) и заменил на пример с сэмплами.
На счёт поддержки WinXP. Использую VS2019 с выбранным SDK для поддержки WinXP, он уже считается deprecated и больше не будет обновляться.
Нужно будет на github залить, как-нибудь позже. Пока что тестируйте.

Оффлайн SeregaZ

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

сейчас буду пробывать новую версию.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
и сейчас осталось в требованиях наличие этого визуал как его там?
Нет, в версии GEMSPlayLibrary_v1_winxp.7z (и в v2 оставил) я сделал статическую компоновку, все runtime библиотеки были вставлены в DLL и exe. Это и поддержка WinXP меняется в свойствах проектов и всё.
--------
Кстати, можно было делать не статическую компоновку, а класть dll, которые люди скачивают с левых сайтов, когда им пишет программа :) Так тоже экономится память, если несколько dll и exe лежат рядом, но я не знаю как там WinXP.
« Последнее редактирование: 24 Март 2020, 01:04:03 от Sharpnull »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2506
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
так что на 7 что на ХР играет замечательно, вылетов нет. загружал пару десятков раз попеременно эти комплекты. единственное - громкость. в треках есть команда называется mastervolume - для дюновского трека она 13. для не дюновского не знаю. видимо там вовсе не установлено этой команды. это глобальная громкость. чем число больше - тем тише. 1 или 0 максимальная громкость. по идее при сбросе, точнее при инициализации банков GEMS - этот параметр должен сбрасываться в максимальную громкость. сейчас же если запустить тот первый комплект с недюновским треком - он играет громко. после запустить дюновский (то есть сработает mastervolume) и после опять вернутся к первому - он будет играть тише, чем изначально он запускался. то есть сброс, точнее инициализации видимо происходит не совсем полностью.

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

Добавлено позже:
Нет, в версии GEMSPlayLibrary_v1_winxp.7z (и в v2 оставил) я сделал статическую компоновку, все runtime библиотеки были вставлены в DLL и exe. Это и поддержка WinXP меняется в свойства проектов и всё.
это просто колбаса! спасибо.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 4999
    • Просмотр профиля
SeregaZ, есть какой-то
static UINT8 MASTERATN; // [15CF] master attenuation is 7 frac bits (0 = full volume)Он в начале 0, потому что глобальный, после меняется только в seqcmd() и в gems_loop(), если была команда. То есть получается, если не было явной команды, то будет что раньше.
В GemsPlay.c много глобальных переменных, которые не инициализруются в gems_init(), там даже осталось сообщение:
// TODO: memzero everything elseДобавил обнуление в gems_init() для MASTERATN, попробуйте обновлённые dll и lib.