Closed Wohlstand closed 5 years ago
Interfacing with the core is really not simple due to nature of the project. It requires 'delays' between write commands. I've already wrote wrapper code for VGMPlay which simplifies interfacing with the core. Look here: https://github.com/vgmrips/vgmplay/blob/master/VGMPlay/chips/ym3438.c https://github.com/vgmrips/vgmplay/blob/master/VGMPlay/chips/ym3438.h
Your interface functions will be look something like
write0(a,d)
{
OPN2_WriteBuffered(chip,0,a);
OPN2_WriteBuffered(chip,1,d);
}
write1(a,d)
{
OPN2_WriteBuffered(chip,2,a);
OPN2_WriteBuffered(chip,3,d);
}
run(count,out)
{
OPN2_GenerateStream(chip,out,count);
}
You'll probably need to change OPN2_GenerateStream to match your sample_t data type.
Thanks, I'll check out this at evening when I'll come to home from my job place
Okay, I have got it working at me, but I got next issues:
//Before (produces distorted notes)
PokeO(card, port, 0xA0 + cc, x2 & 0xFF);
PokeO(card, port, 0xA4 + cc, (x2>>8) & 0xFF);//Set frequency and octave
//After (works fine)
PokeO(card, port, 0xA4 + cc, (x2>>8) & 0xFF);//Set frequency and octave
PokeO(card, port, 0xA0 + cc, x2 & 0xFF);
Maybe I need to initialize it a bit differently? (I gave same values as to GME's emulator I using now)
cardsOP2[i] = new ym3438_t;
std::memset(cardsOP2[i], 0, sizeof(ym3438_t));
OPN2_Reset(cardsOP2[i], (Bit32u)_parent->PCM_RATE, (Bit32u)(7153353.0 * 2.0));
Where PCM_RATE
is an output sample rate (I usually set it as 44100 Hz)
I have posted my current stuff into the separated branch https://github.com/Wohlstand/libOPNMIDI/tree/nuked-opn2
In the src/opnmidi_opn2.cpp
you can find the usage of the chip emulators
1) Yes. Frequency write order MUST BE reversed. 2) Hmm. x86 build of GPGX with my core loads CPU up to 14% on i5-3210M and x64 loads up to 4% on i7-4790 desktop. GPGX obviosly runs only one core. 3) Actually Genesis runs YM3438 at 7,6704545 MHz rate(7,600489 MHz on PAL Mega Drive).
P.S. Your emulator has much better volume model (I don't know why, but on old emulator native logarythmic volume was too strong and linealizing formula for OPL3 wasnt completely worked and volume still be logarythmic, but here I see volume is linealizyng fine ;-)
Did you remove 2.0 factor for master clock?
Yes, I have tried to do that, and then I got lower sample output which then I tried to fix by division of PCM_RATE and lag is still same, even without rare division.
You can try out my libOPNMIDI in action (I did thematic branch with experimental code) by using test pro file for Qt Creator which builds simple player that will receive path to WOPN bank file and then path to MIDI file to play. It needs for SDL2.
P.S. For comparison what I mean LFO iterating faster, a short fragments dumped from both GME's and Nuked emulators:
Okay, after your pull request LFO and CPU overload troubles are gone! Anyway, I see your OPN2 emulator requires much more power than same OPL3 emulator you did before, therefore I can't process more than 3 chips on same CPU core without getting of choppy playback.
P.S. Is presented DC offset and noises is normal or it's a bug of the resampler?
Noisy output is normal as YM2612/3438's output is 9 bit wide. In case of YM2612, output is even more noise due to 'ladder' effect glitch, which was partially fixed in discrete YM3438 and completely fixed in ASIC YM3438. I have no idea what causes DC offset. Which chip type do you use(YM2612 or discrete/asic YM3438)? In case of the YM2612 it is likely due to 'ladder effect' emulation.
I did used discrete YM3438 mode, I'll try out ASIC mode...
EDIT: Yeah, I have used OPN2_SetOptions(ym3438_type_discrete);
which was totally incorrect (because of logic, noisy YM2612 was in use), when I have replaced that with OPN2_SetChipType(ym3438_type_asic);
, noice is gone, and DC offcet gone too!
Okay, why this difference in attack/decays angle between of emulators?
I have tried to play around of instrument's register write order (to do same that was in specification I used to learn the chip, where frequency byte order is also reversed), but I got same result with no matter to write order - attack/decay is longer on Nuked emulator than on GENS's (I found which emulator was originally until it came into GME, and I think, it is outdated and needs for update).
Gens' YM2612 core is quite outdated. I recommend to switch MAME core instead since it models internal work of YM2612 much more accurately.
Okay, I'll try to use it when I'll come to my home. (I'll also replace emulator in the GME's core too) Also, with Nuked I see that even with three chips I getting clipping on a wide polyphony, so, I would to make volume reducer on output of each chip to avoid possible clipping with using of multiple chips (and multi-threading because Nuked OPN2 is much more powerful than even Nuked OPL3. Also, which of those chips you like more yourself? Proc of OPL is 8 various source waveforms and yeah, float32 sound output while OPN has sine only and 9-bit sound output as you have told, but proc of OPN is more built-in complex algorithms to combine operators, and yeah, porting of instruments between of those chips is not a simple task to repeat almost same output if that possible)
Okay, keeping this issue be opened is no more needed. I'll close it.
Hi @nukeykt
I think there is some trouble with the VGMPlay wrapper WriteBuffered
, in case the buffer would be overflowed.
I noticed how some register writes don't seem to pass through, and this routine is under high suspicion.
As I observe, this part of the routine must dequeue the buffered messages in case of a full buffer. If my understanding is correct, this has some problems.
writebuf_last
as the position to dequeue, in several occurrences, but it's the write pointer(?). Should this not refer to writebuf_cur
instead?port
flag 0x04 after the message is consumed from the queue, contrary to this part of Generate
.
https://github.com/vgmrips/vgmplay/blob/c086bd2334d0efa02fc08815294c2674276eb367/VGMPlay/chips/ym3438.c#L1512-L1523Help will be very appreciated. I hope that my remarks above are making sense.
It's related to the effort of building a feature-limited OPNA on top of Nuked-OPN2. https://github.com/rerrahkr/BambooTracker/pull/94#issuecomment-584504828
Sorry don't bother, I couldn't reproduce it on this repo's latest code, I'll ask again if I need.
Hello!
I am trying to figure out how to work with the new emulator to use it in my libOPNMIDI and in the OPN2 Bank Editor where I used emulator I got from GME project. It has
void write0( int addr, int data );
,void write1( int addr, int data );
functions to write register data (like in case of OPL3 emulators) and thevoid run( int pair_count, sample_t* out );
to generate an audio output chunk of specified length based on current state of data in registers. In case of new emulator it provides API which is similar to the real chip without having of a good manual to learn how to deal with it.Can you implement those functions or provide a manual to let everyone easier control the chip?