ShootersForever.com Forum Index

GoldenEye 007 Nintendo 64 Community, GoldenEye X, Nintendo 64 Games Discussion
GoldenEye Cheats, GoldenEye X Codes, Tips, Help, Nintendo 64 Gaming Community


GoldenEye 007/Perfect Dark HD Music (48kHz/32-bit)

 
Post new topic   Reply to topic    ShootersForever.com Forum Index -> GoldenEye 007
View previous topic :: View next topic  
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Fri Feb 04, 2022 12:26 pm    Post subject: GoldenEye 007/Perfect Dark HD Music (48kHz/32-bit) Reply with quote Back to top

There were always minor (or major) issues in my previous HD restores of the GoldenEye 007 OST.

I’ve spent the past 2 months working day-in and day-out on a tool I call Nintendo Synthy-4 whose job is to render Nintendo 64 music the way Nintendo 64 did, but with high-resolution versions of all of its routines.
I’ve been debugging the games and copying every routine exactly, taking care of every little detail. For example, when you change a track’s volume to 0, it takes 4 samples to reach 0 volume.
And here’s the exact vibrato routine (except in 64-bit instead of 32-bit):
Code:
      /**
       * Gets the vibrato depth given the game's 0-255 value.
       *
       * \param _ui8Val The value to convert.
       * \return Returns the converted vibrato depth.
       */
      static double               VibratoDepthToReal( uint8_t _ui8Val ) {
         return std::pow( 1.030992984771728515625f, _ui8Val );
      }


Code:
         void                  Set( uint8_t _ui8Rate, uint8_t _ui8Depth, uint8_t _ui8Delay, uint32_t _uiMasterSamplingRate ) {
            dDepth = VibratoDepthToReal( _ui8Depth );

            tbDelay.SetRate( ((1.0 / 30.0 / 2.0) * _ui8Delay) * _uiMasterSamplingRate );
            tbRate.SetRate( ((1.0 / 30.0 / 2.0) * (259 - _ui8Rate)) * _uiMasterSamplingRate );
         }


Code:
         /**
          * Gets the current vibrato depth.
          *
          * \return Returns the current vibrato depth.
          */
         double                  Value() const {
            if ( dDepth ) {
               double dTmp = std::sin( tbRate.Time() * NS4_TWO_PI ) * dDepth;
               // The cast is only a performance hack by the game, so removing it could be an “as-intended” routine with full precision.
               double dRate = std::pow( 1.00057780742645263671875f, static_cast<int32_t>(dTmp / 2.0) );
               return dRate;
            }
            return 1.0;
         }


Nintendo Synthy-4 has a huge focus on accuracy, and that goes for the timing as well. I’ve taken measures to ensure it is always sample-accurate and never drifts.
The real game will trigger all of the notes on a tick starting on the same sample, but the time between ticks can vary.
Nintendo Synthy-4 is an offline renderer, so it can take as much time as it needs to render the perfect result. Every note starts on exactly the correct sample, no matter how long the recording is.
It does not accumulate drift either.
For a computer, (1/7.0)+(1/7.0)+(1/7.0)+(1/7.0)+(1/7.0)+(1/7.0)+(1/7.0) == 0.9999999999999997779553950749686919152736663818359375.
But Nintendo Synthy-4 handles all timers like this: 1/7, 2/7, 3/7, 4/7, 5/7, 6/7, 7/7, etc. This means that tiny inaccuracies are not accumulated. Every single sample in the final result is as accurate as every other sample.


I’ve had to use approximations for a lot of things before, but now even the reverb is accurate, with one difference.
This is the actual game’s reverb taps:

Notice it drifts away from 0 toward the end. That is undesirable so I filtered that back into a nice clean reverb. I also eliminated the artifacts that cause major buzzing.

So what you get is the exact reverb but filtered to sound nice and clean.


So this is a truly accurate HD restore of GoldenEye 007 (48 KHz/32-bit):
https://www.youtube.com/playlist?list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce


Samples:
https://www.youtube.com/watch?v=7qacI0HkjrY&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=9
https://www.youtube.com/watch?v=vlrr1SYRXew&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=51

And from Perfect Dark:
https://www.dropbox.com/s/3ia8dwsii0p4d0b/093%20Alien%20Conflict.wav?dl=0
https://www.dropbox.com/s/memh7nhj8moacdj/092%20Maian%20Tears.wav?dl=0
https://www.dropbox.com/s/u93d43skg7ytlvs/065%20Deep%20Sea-%20Nullify%20Threat.wav?dl=0


Enjoy!


L. Spiro


Last edited by L. Spiro on Tue Jun 21, 2022 4:21 pm; edited 1 time in total
 
View user's profile Send private message
Carnivorous
Moderator
Moderator


Joined: 15 Oct 2016
Posts: 657
Location: Ukraine

 PostPosted: Fri Feb 04, 2022 1:13 pm    Post subject: Reply with quote Back to top

Hi. I had a listen to Alien Conflict render and noticed two volume differences with an N64 in-game playback. I've uploaded a 10 second compare here of your render and in-game here. The reference N64 recording is using emulation with Azimer's HLE.

At 2.7 seconds channel 7 note D4 seems louder than reference.
At 8.3 seconds channel 7 note A#3 seems louder than reference.
 
View user's profile Send private message
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Fri Feb 04, 2022 6:24 pm    Post subject: Reply with quote Back to top

It’s not that the notes are different volumes, it’s that the vibrato has a slightly different tone in it, which I’ve heard too, but the code I posted above is what the game really is using.
Even though all of the math is correct, it still sounds deeper in the game, but only sometimes, IE either when 2 vibrato notes are layered or in the low tones.

I’ve investigated several possibilities without finding any issues, so currently my best guess is that the 2 notes are interacting with each other or the reverb to cause that. I originally thought that the 2 notes were out of sync by just a sample or so and causing dissonance that changes the tone and perceived volume, but the notes do start on the same sample, so I’m expecting it to be either an accuracy issue or a specific interaction with the reverb.
#1: I removed the artifacts from the reverb that cause a slight enhancement to the bass tones, which may be why it happens on the lower notes.
#2: The Perfect Dark set isn’t final. I actually harvested the reverb from Conker’s Bad Fur Day and used it for these Perfect Dark samples. Both games use the same reverb settings, but Conker’s Bad Fur Day applies a bit of smoothing to it and has a different buffer length. I figured it would sound almost the same but just a bit cleaner, but it may also change how low frequencies interact with it, and may be creating this issue.
#3: Even aside from the reverb being from a different game, I am using a slightly shorter delay time. Low frequencies in the original may very well be combining with the reverb to amplify certain frequencies, an effect that might be lost due to this difference in my versions.

But all of the differences in reverb are known to me and just meant to fill a gap and give me some results.
I will address all of these issues for the final Perfect Dark set.


I wanted to give some examples from Perfect Dark just for your enjoyment, but they are not on YouTube because they aren’t actually fully done yet.
Sorry about that!


L. Spiro
 
View user's profile Send private message
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Sat Feb 05, 2022 8:41 am    Post subject: Reply with quote Back to top

Oops!

I introduced a reverb bug while refactoring before creating the GoldenEye 007 set.
I’ve updated the WAV pack: https://www.dropbox.com/s/62x3c33yl2oqdg7/GoldenEye%20007%20HDU.rar?dl=0
And only a few videos that were impacted the most by the issue.
My shame is eternal.


L. Spiro
 
View user's profile Send private message
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Sun Feb 20, 2022 8:58 pm    Post subject: Reply with quote Back to top

Sorry for the confusion over the accuracy of the Perfect Dark set! Having not solved some of the issues, I had used approximations for things—such as the reverb—that would qualify them as more of a beta set!
Those issues did not impact GoldenEye 007, but I found yet-another bug in the reverb (fixed), and I’ve gotten better at harvesting reverb and filtering them, so I want to make a final pass on GoldenEye 007 soon.

But until then, I want to make up for the confusion with a little sampling!
These are 48 KHz/32-bit!
https://www.dropbox.com/s/08bt6sagwi3k8ws/Carrington%20Villa-%20Hostage%20One.wav?dl=0
https://www.dropbox.com/s/r0yxu50ain7s740/Carrington%20Villa-%20Hostage%20One%20Intro-%20Negotiate%20This%21%20%28Secret%20Agent%29.wav?dl=0
As they say: Why approximate when you can exactimate? Laughing
No aspect of these are approximate! All algorithms that are applied to notes (note velocity, envelopes, vibrato, pitch-bend, tremolo, stereo-effect, etc.) are replicated using 64-bit fully-detailed implementations! Studio fade-out with LPF down to 100 Hz and normalization to -0.1 dB all done internally in 64-bit double precision before being converted to PCM using nearest-neighbor rather than truncation!

Even the stepping pattern in the vibrato is accurate (top: Game; bottom: Nintendo Synthy-4)!


The reverb? Yep! Exact!

These ain’t yo mamma’s HD restores!
Woo, what was in those brownies?


Here are some more samples:
https://www.youtube.com/watch?v=TqK4CnDnIUQ&list=PLWsnao9n727NxWzs8QHsxbhioLxyQOuhb&index=29
https://www.youtube.com/watch?v=FSLkh51bAIo&list=PLWsnao9n727P4FVN44f8LuB9jogjDd0k4&index=31
https://www.youtube.com/watch?v=HUEnjdc3vgU&list=PLWsnao9n727MDQWUUGqHQWPbRKlFmDBq7&index=190

Notes for browsing the channel: The “HD Ultra” sets are the most accurate, but Jet Force Gemini is an exception (it was kind of a beta run).
Some of the HD Ultra sets are 100% sample-perfect (due to the nature of their reverbs): Super Smash Bros., Super Robot Spirits, and Penny Racers.
The rest (except for Jet Force Gemini) are 100% sample-perfect except that their true reverbs drift away from 0 and also cause buzzes and artifacts that I cleaned out for the HD-ification.

The playlist descriptions have links to the raw downloads, which are 48 KHz/32-bit WAV files with a Songs.txt accompanying file detailing each track.

I’ll get an update to GoldenEye 007 out soon, but for now enjoy!


L. Spiro
 
View user's profile Send private message
Will6546
Agent
Agent


Joined: 14 Jan 2022
Posts: 70
Location: In the Cold Time of-Northern, Mitten: State: area

 PostPosted: Mon Feb 21, 2022 6:09 am    Post subject: Reply with quote Back to top

Hi there L Spiro 🐱 great Heavy work your doing there! Very Complicated for me. When you ever get the um, GE Completed, um, how do I add that to my Rom do I have to use a Audio program, to do that with?

Well, I'm new at all this. So I was Curious thanks fir all your doing! Much luck on your tasks have a better week on that hope it works out great. Cya here. 😎
_________________
If you look further down the list of Tracks you'll see all my Works I done over the years 😎 WiLL
https://www.nfsaddons.com/downloads/nfshs/tracks/
 
View user's profile Send private message Visit poster's website
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Mon Feb 21, 2022 1:31 pm    Post subject: Reply with quote Back to top

The WAV packs are linked in the playlist descriptions. Once you have the WAV files you can do whatever you can do with WAV files!
I am quite certain it is impossible to play 48 KHz/32-bit WAV files in GoldenEye 007 or Perfect Dark, though, but if it is possible someone else here may be able to help you with that!


L. Spiro!
 
View user's profile Send private message
Will6546
Agent
Agent


Joined: 14 Jan 2022
Posts: 70
Location: In the Cold Time of-Northern, Mitten: State: area

 PostPosted: Mon Feb 21, 2022 2:43 pm    Post subject: Reply with quote Back to top

Hi.. I was just asking, if you was trying to do that for both Of the games Ge, an PD was all. What Audio format is both the games speech, an gun sounds anyway. Cause I haven't the Clue. I'm new here. An doing good on ED X7 not bragging, it's fun tho. gnight here ☮️ 😎thanks
_________________
If you look further down the list of Tracks you'll see all my Works I done over the years 😎 WiLL
https://www.nfsaddons.com/downloads/nfshs/tracks/
 
View user's profile Send private message Visit poster's website
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Sun Mar 13, 2022 7:47 pm    Post subject: Reply with quote Back to top

Okay!
There was a bug impacting all of the mono-reverb sets, and I improved my reverb-filtering technology and reverb-harvesting process, and I also changed my export-to-YouTube settings so as not to compress the tracks.
If you heard some imbalances in the GoldenEye 007 set I had released earlier, that is all fixed.
It took 6 long years, but we finally got there!

The Files
https://www.dropbox.com/s/62x3c33yl2oqdg7/GoldenEye%20007%20HDU.rar?dl=0
48 KHz/32-bit.

The Playlist
https://www.youtube.com/playlist?list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce

The Samples
https://www.youtube.com/watch?v=amDKp1T3P6U&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=6
https://www.youtube.com/watch?v=uK4kHb22sZE&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=51
https://www.youtube.com/watch?v=p6zbCJoF8LU&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=14
https://www.youtube.com/watch?v=YVUO90EbBTM&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=54
https://www.youtube.com/watch?v=jnPeXcU_2No&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=9

The Inside
I think people find the behind-the-scenes interesting, so here are some peeks!
This is Nintendo Synthy-4, and while I intend to make it public at some point, for now I am organizing the files to convert and using macros to change certain run-time settings between games.

GoldenEye 007 is the only game using NS4_MASTER_REVERB_OFFSET, since all other games bake the tap offsets into their tables.
GoldenEye 007 is an NS4_CURVE=40.0 game while Perfect Dark, Banjo-Kazooie, Banjo-Tooie, Jet Force Gemini, Conker’s Bad Fur Day, and Donkey Kong 64 are NS4_CURVE=20.0 games.
What’s this?
The MIDI standard recommends that cc7 (main volume) be handled using log10(X)*40.0 to get dB, rather than using the standard linear->dB equation of log10(X)*20.0.
The SDK shipped compliant with the standard and later Rare (Graham Smith specifically) gutted the SDK and made this among other changes (at the request of Graeme Norgate).


“Taps” refers to how the reverb routines transport individual samples from the “wet” buffer through a pipeline.
If you sent a single 1.0 dry sample through the reverb process, the resulting output is a map of where the wet buffer was copied and pasted by the reverb routine—the taps that characterize the reverb routine are exposed.

In this image, the top image is Conker’s Bad Fur Day reverb captured using a single sample as above, and the bottom is a filter I apply to re-center the waves.


The individual taps are then harvested into a table.

That large downward tap at the start of the filter image is here in the tap buffer at index 0, offset 192 samples (in the original game’s Hz), value -0.06183050019837032.

Sometimes I regret the choices I have made in my life when my screen looks like this at 3:00 AM!


Some of the internals.

Notice that handling pan doesn’t just change a track pan value, it instead checks for bActive and updates each note instead. This reveals a quirk about how MIDI is handled by the Nintendo 6 base SDK: Panning, volume, and pitch-bend changes are not applied to notes that are in the release phase! Additionally, each active note maintains its own pan, because notes start on whatever the active pan is for a MIDI track, but interpolate when panning is updated. So an active note might be spending 16 samples to interpolate its pan from the old value to the new track pan, but a new note that is triggered will just start on the current track pan. That interpolation is note-specific!

Below that you will see how program changes are handled. Have you ever wondered why you can play back the SubDrag exported MIDI files and the pans and volumes are sometimes—but not always—wonky?
This is the secret sauce: (ui32TickOfLastVolChange != teEvent.ui32Time || bIsTick0)

If you implement these 3 rules strictly, you will be able to get beyond those annoying inaccuracies:
#1: Changing instruments updates volume, pan, and pitch-bend. Pitch-bend is set to 0, while volume and pan are taken from the instrument’s volume and pan properties. These are almost always set to 0x7F and 0x40. These values simply overwrite the track’s current volume and pan properties.
#2: When gathering MIDI events to process during the current frame, the game’s MIDI engine will first look for a program change and handle it first before handling the other events queued up for that MIDI tick. So if a pan and program-change are on the same tick, and the pan is before the program-change in the MIDI file, this means that first the program change will update the pan, volume, and pitch-bend and then then pan event will be handled, which will overwrite the pan set by the program change. Effectively, the program change is sorted to come before all of the other events in the same MIDI tick, but only 1 program change per tick gets sorted up to the front of that tick.
#3: Tick 0 has an implicit program-change to instrument 0.

This means that the default volume and pan for each MIDI track is whatever the instrument pan and volume are for instrument 0. They do not default to 0x7F and 0x40.
And if you combine rules 2 and 3, you get the reason that all Nintendo 64 composers were confused and vowed revenge on whoever programmed the SDK.
As an example, Dan Hess told me that sometimes he couldn’t figure out why he needed to set the pan or volume twice for it to work, and if you browse all of the Rare MIDI files from all of their games you will see that they always leave space at the start of the MIDI file specifically to avoid the dreaded tick 0.

If you are developing the Nintendo 64 SDK MIDI routines, you will realize that when a composer puts a program-change, a pan, and a volume all on the same tick, the intent is to play the given sample at the volume and pan the composer specified on that tick.
But you know that the MIDI data could be coming from any utility, and that those events might be sorted in their MIDI tool to put the program-change after the other events on the tick.
So you sort the events on a given tick to always handle the program change first, regardless of the order of the events in the MIDI file.
And there was much rejoicing. The intent is always expressed correctly.
You know that handling program changes is expensive, so you limit the system to only sorting up to the first program change you encounter—multiple program changes should never be on the same tick.
But now you add that implicit program-change to instrument 0 at tick 0 and now every composer is angry and confused.
The default set-program command causes your routine to not perform the above sorting on tick 0. It stops searching for program-change events after it finds the first one among the queued events, so now tick 0 behaves weirdly when the composer’s MIDI tool puts the tick-0 program change (which was standard for these composers to do before Nintendo 64 chungled their lives) after the tick-0 pan and tick-0 volume, the engine will handle the pan, then the volume, then the program change, which overwrites the volume and pan.


This tick-0 quirk has caused the bugging of many Nintendo 64 OST’s.
For example, Chameleon Twist isn’t a mono OST, it just sets its pan and volume on tick 0 and then those were overwritten when the tick-0 non-sorted program change gets handled.
https://www.youtube.com/watch?v=TX5R8JZ6_B8&lc=Ugx_DDUtJu7_eKkOVgJ4AaABAg See first comment.
In Chameleon Twist 2, Koichi just gave up on figuring this all out and, realizing that the volumes he was getting were tied to the instrument volumes, he just set the instrument volumes to the levels he wanted and composed around that.

There were literally 0 studios using the original Nintendo 64 SDK who knew what the hell what happening and how to handle it correctly (a tool to move an tick-0 program changes to come before any pan/volume events on a given track), so all studios either got bugged by it or worked around it. At Rare the in-house solution was to simply avoid tick 0. This is why you see them setting pans and volume and programs on ticks 1 and later.

However, mistakes could still be made.
Caverns X in GoldenEye 007 has strings that are incorrectly too loud due to all of these quirks.
I may release a fix for this after I have a talk with Graeme about it.





Well I know that most of you are only here for the goods, but I hope that bit of technical exploration was also interesting!
Enjoy!


L. Spiro
 
View user's profile Send private message
Thundera8589
Secret Agent
Secret Agent


Joined: 12 Aug 2015
Posts: 351

 PostPosted: Tue Mar 15, 2022 3:42 am    Post subject: Reply with quote Back to top

I've mentioned this in the past to you about the MIDI used in GE-X and how some of the instruments had distortion sounds and some other instruments didn't sound loud or noticeable when compared to how they sound in the original Goldeneye game. You told me something about it having to possibly do with the settings like the pan, drums, volumes etc that were changed for Perfect Dark. You also mentioned on what it might've been.

Now with these new tools of yours I'm wondering now if it is possible that you can edit the current GE MIDIs that are used in GE-X to match up the pan, volume, drum, db, etc to be exactly like GE? You also mention here how GE had a max 40db while games like Perfect Dark only used 20db. Could that be another reason why some of the MIDI instruments don't sound as loud as they did originally GE compared to GE-X?

I know this might be too much to ask of you but in your free time can you check GE-X in-game music and sound effects and Goldeneye's as well and compare them this way you know what I am talking about?

Very insightful info on the MIDI sounds of these games.
_________________
"The Eye of Thundera, give me sight beyond sight!"
 
View user's profile Send private message
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Tue Mar 15, 2022 1:52 pm    Post subject: Reply with quote Back to top

It will be a bit difficult for me to get into the weeds with GE-X, however I don’t think I need to!
After doing so many OST’s I can tell by-ear which games use a 40 curve vs. a 20 curve. Not without a reference for comparison of course, but the references in this case are the original tracks.

So if I hear the way the music is wrong I can probably diagnose the issue fairly quickly.
As a quick rule of thumb, if Perfect Dark sounds wrong, then GoldenEye 007 played through that same MIDI engine should sound correct, and vice versa.


So if only one of them sounds wrong, just let me know which one and that will tell me everything I would need to know to make a converted set that should sound correct.

If both sound wrong in different ways, just give me recordings of each and I can probably diagnose the issue based off all the issues I have encountered doing HD restores for 6 years.

Also just a note on the dB point! It’s not that they are limited to a dB, it’s a conversion from linear to dB and then back to linear.
Assume you have a cc7 value of 64, or (64/127)=0.5039370059967041015625. The MIDI standard simply uses a different conversion from linear to dB.
MIDI Linear -> dB: log10( 64.0 / 127.0 ) * 40.0 = -11.904949188232421875 dB
Standard Linear -> dB: log10( 64.0 / 127.0 ) * 20.0 = -5.9524745941162109375 dB


The conversion back to linear is the same either way: pow( 10, dB / 20 ).
-11.904949188232421875 dB = 0.253952503204345703125
-5.9524745941162109375 dB = 0.5039370059967041015625

So if you have a cc7 value of 64, in GoldenEye 007 that should be 25.3952503204345703125% volume, whereas in Perfect Dark that would be 50.39369964599609375% volume.
Note that when using a 20.0 curve, that’s just standard linear -> dB -> linear, so you can cut out the conversion to dB and just use 64/127 directly.

Here are a few values to compare between the 2 standards.
cc7=1
Curve.40 = 0.000062000122852623462677001953125
Curve.20 = 0.0078740157186985015869140625

cc7=44
Curve.40 = 0.12003223598003387451171875
Curve.20 = 0.3464566767215728759765625

cc7=64
Curve.40 = 0.253952503204345703125
Curve.20 = 0.5039370059967041015625

cc7=90
Curve.40 = 0.50220096111297607421875
Curve.20 = 0.708661377429962158203125


Notice that Curve.40 can get significantly quieter than Curve.20, which is why the MIDI standard recommends it. It covers a greater range of volumes.
And these values stack because the SDK uses the same routine to handle all volume adjustments made to samples.
So if the envelope, note velocity, and track volume are all 64:
Curve.40 = 0.253952503204345703125 * 0.253952503204345703125 * 0.253952503204345703125 = 0.016377873718738555908203125
Curve.20 = 0.5039370059967041015625 * 0.5039370059967041015625 * 0.5039370059967041015625 = 0.12797605991363525390625



Here’s a snippet of my code for handling each note playing a sound on a track:

Code:
               if ( vNotes[J].psSoundbankSample ) {
                  double dVal = vNotes[J].sSampler.Sample();
                  dVal *= MidiLevelToLinear( vNotes[J].eEnvelope.CurLevel() );
                  double dTremPhase;
                  double dTremAmnt = vNotes[J].tTremolo.Values( dTremPhase );
                  dVal = (dVal * (dTremAmnt * dTremPhase + 1.0)) / (1.0 + dTremAmnt);
                  if ( vNotes[J].bLpf ) {
#ifdef NS4_USE_NEW_LPF
                     dVal = CWavLib::BiQuadFilter6_Recursive_Step( dVal, vNotes[J].dA0, vNotes[J].dA1, vNotes[J].dA2,
                        vNotes[J].dB0, vNotes[J].dB1, vNotes[J].dB2, vNotes[J].sFilterSamplesB, vNotes[J].sFilterSamplesA );
#else
                     dVal = CWavLib::BiQuadFilter5_Recursive_Step( dVal, vNotes[J].dA0, vNotes[J].dA1, vNotes[J].dA2,
                        vNotes[J].dB0, vNotes[J].dB1, vNotes[J].sFilterSamplesB, vNotes[J].sFilterSamplesA );
#endif   // NS4_USE_NEW_LPF
                     //dVal = clamp( dVal, -1.0, 1.0 );
                  }
                  
                  if ( m_ui8DistortionControl && msState.ui8State[m_ui8DistortionControl] ) {
                     double dClipLevel = DistortionControlToClipLevel( msState.ui8State[m_ui8DistortionControl] );
                     dVal = clamp( dVal, -dClipLevel, dClipLevel );
                  }
                  dVal *= MidiLevelToLinear( vNotes[J].liVolumeInterpolator.Value() / 127.0 );
                  dVal *= MidiLevelToLinear( vNotes[J].ui8Vel );
                  dVal *= MidiLevelToLinear( vNotes[J].psSoundbankSample->ui8Vol );
                  dVal *= MidiLevelToLinear( msState.ui8State[NS4_TRACK_MASTER_VOL] / 255.0 );
                  dVal *= MidiLevelToLinear( liMasterVol.Value() / 127.0 );

                  


                  int32_t i32Pan = int32_t( (std::round( vNotes[J].liPanInterpolator.Value() ) - 0x40) + int32_t( vNotes[J].psSoundbankSample->ui8Pan ) );
                  i32Pan = clamp( i32Pan - 1, 0, 126 );
                  double dL = std::cos( (i32Pan / 126.0) * NS4_HALF_PI );
                  double dR = std::sin( (i32Pan / 126.0) * NS4_HALF_PI );

                  if ( m_ui8StereoEffectControl && msState.ui8State[m_ui8StereoEffectControl] ) {
                     dL = -dL;
                  }
                  if ( _paWet ) {
                     if ( dVal * dWetLevel ) {
                        // The reverb buffer is optionally clamped because the game operates on 16-bit PCM samples,
                        //   limiting the range to [-1..1].  This gives it some of that Nintendo 64 feel,
                        //   though we dampen the effect with an LPF later.
                        // It is important to clamp here to mimic how the game accumulates reverb samples.
                        if ( _paWet->size() == 1 ) {
                           if ( (*_paWet)[0].size() <tbWavTime>size() == 2 ) {
                           if ( (*_paWet)[0].size() <= tbWavTime.CurTick() ) {
                              (*_paWet)[0].resize( _troOptions.uiMaxSamples );
                           }
                           if ( (*_paWet)[1].size() <= tbWavTime.CurTick() ) {
                              (*_paWet)[1].resize( _troOptions.uiMaxSamples );
                           }
                           (*_paWet)[0][tbWavTime.CurTick()] += dVal * dWetLevel * dL;
                           (*_paWet)[1][tbWavTime.CurTick()] += dVal * dWetLevel * dR;
                           if ( m_bClampReverb ) {
                              clamp( (*_paWet)[0][tbWavTime.CurTick()], -1.0, 1.0 );
                              clamp( (*_paWet)[1][tbWavTime.CurTick()], -1.0, 1.0 );
                           }
                        }
                     }
                     dVal *= dDryLevel;
                  }

                  aResult[0][tbWavTime.CurTick()] += dL * dVal;
                  aResult[1][tbWavTime.CurTick()] += dR * dVal;
               }


MidiLevelToLinear() is my routine for handling the Curve.40/Curve.20 level calculations. You can see all the places it needs to be applied for a correct sound.
Note that there is no master volume or track master volume in GoldenEye 007 (Perfect Dark has track master volume; Super Smash Bros. and Kirby 64: The Crystal Shards are games with master volume), so these remain at default values that result in no change to volume.
m_ui8StereoEffectControl defines which control activates the stereo effect, which is used in Perfect Dark and Conker’s Bad Fur Day, and is set to 65 (IE, MIDI control 65 handles stereo effect).
And my code reveals how that stereo effect is achieved, by simply inverting the left channel.
m_ui8DistortionControl is used by Jet Force Gemini and Conker’s Bad Fur Day and is set to 35 (MIDI control 35/cc35 changes the amount of the distortion effect), which my code reveals is just a clamping function at a specific level defined by the value in cc35 (note that it is not linear; there is a custom mapping curve applied to translate cc35 into the clip level).


I went into all these details partly because it is probably interesting to a lot of people, but also because it also shows that it may not be enough to modify just the MIDI files. The envelopes are in the SoundFont and would also need to be converted.
It may be a larger task than I have time to do, although later I will have to add my own support for SoundFonts in order for me to support GameBoy Advance, Nintendo DS, and Nintendo 3DS games.

Anyway, let’s start with either a sample of the baddy-bad or let me know whether Perfect Dark sounds fine while GoldenEye 007 sounds babby-bad.


L. Spiro
 
View user's profile Send private message
Thundera8589
Secret Agent
Secret Agent


Joined: 12 Aug 2015
Posts: 351

 PostPosted: Wed Mar 16, 2022 5:22 am    Post subject: Reply with quote Back to top

While I don't have the necessary tools to extract tracks or any emulators or what not at the moment. I will say the most notable tracks that sounded off in GE-X from the og GE were Control, Cradle, Frigate X, Silo X, Jungle, and Elevator Music 2. There might be others but I can't quite remember at the moment. By the way, Jungle, Control, and Elevator Music 2 have a noise distorted sound in one of it's instruments that can be heard if you play the track in-game using headphones at max volume.

Also it isn't just the tracks but the overall sound quality as well. Like even the sound effects in GE-X when you reload a weapon or pick up ammo. The tick sounds they make are not as loud and clear as the og GE.

It's probably as you mentioned and has to do with Perfect Dark's Soundfont in general. Perhaps it needs to be modified. Not sure if you can pull it off with your new sound tools.
_________________
"The Eye of Thundera, give me sight beyond sight!"
 
View user's profile Send private message
L. Spiro
Agent
Agent


Joined: 27 Feb 2009
Posts: 116
Location: Cupertino, CA

 PostPosted: Sun Jun 19, 2022 10:39 am    Post subject: Reply with quote Back to top

This will be the last update regarding HD versions of the music.
I mentioned before that the only major update left to make was to parse the games’ reverb parameters manually in HD for fully detailed accurate HD reverb.
This makes a huge difference in the final quality and warrants an update. In addition to the reverb now having more-accurate impulses and cleaner fall-off/HD detail, it now also has accurate LPF’ing at the correct frequencies, taking care of every last detail to get the original sounds accurate but in HD.

Samples that show off reverb:
https://www.youtube.com/watch?v=05TP61nGoRk&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=5
https://www.youtube.com/watch?v=ebFuN5k-LrI&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=92
https://www.youtube.com/watch?v=AJDXQgWjjxc&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=38

https://www.youtube.com/watch?v=aEpWB1NQc-k&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=6
https://www.youtube.com/watch?v=fW9OGGp6Qp4&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=11
https://www.youtube.com/watch?v=i7zK2j4R0Oc&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=19
https://www.youtube.com/watch?v=BN0z2JUB34E&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=38

Other showcases:
https://www.youtube.com/watch?v=mMPerZ4KrWY&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=25
https://www.youtube.com/watch?v=o80LTCvOs6o&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=65
https://www.youtube.com/watch?v=ebFuN5k-LrI&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=92
https://www.youtube.com/watch?v=5j5uR9zFp-w&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=93

https://www.youtube.com/watch?v=hYSOpqsxd2M&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=9
https://www.youtube.com/watch?v=GD9VNlfwemY&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=14
https://www.youtube.com/watch?v=gDUBFx3_l2M&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=16
https://www.youtube.com/watch?v=Zzb7GfBEo2U&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=37
https://www.youtube.com/watch?v=rEg7iTqfF8E&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=45
https://www.youtube.com/watch?v=IJYyWLb4l8A&list=PLWsnao9n727PLCC-QTWwhYhEdqXd5GPce&index=54

Bonus Material:
https://www.youtube.com/watch?v=vnTegoxNpO4&list=PLWsnao9n727Pnx_ZoOWnF1icxWhD3RSKB&index=100
https://www.youtube.com/watch?v=9zyEo0TIfSM&list=PLWsnao9n727NHRitGRw9a-D7D1V3sFbrU&index=31
https://www.youtube.com/watch?v=vhZLDvZGl2c&list=PLWsnao9n727NHRitGRw9a-D7D1V3sFbrU&index=40
https://www.youtube.com/watch?v=zzg1LG_p1_k&list=PLWsnao9n727NHRitGRw9a-D7D1V3sFbrU&index=50
https://www.youtube.com/watch?v=yUONYxLgVqw&list=PLWsnao9n727NHRitGRw9a-D7D1V3sFbrU&index=63
https://www.youtube.com/watch?v=64IbMiXSpw4&list=PLWsnao9n727NHRitGRw9a-D7D1V3sFbrU&index=74
https://www.youtube.com/watch?v=WmucrWjyKj4&list=PLWsnao9n727MpoQlhgWGIhb5qmWrkUGQf&index=6
https://www.youtube.com/watch?v=-pi6qY7Gp_o&list=PLWsnao9n727MpoQlhgWGIhb5qmWrkUGQf&index=23
https://www.youtube.com/watch?v=bXFjpSM0olQ&list=PLWsnao9n727MpoQlhgWGIhb5qmWrkUGQf&index=65


Links to uncompressed WAV files (48 kHz/32-bit) in the playlist descriptions.
Enjoy!


L. Spiro
 
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    ShootersForever.com Forum Index -> GoldenEye 007 All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Cobalt 2.0 BB theme/template by Jakob Persson.
Copyright 2002-2004 Jakob Persson


Powered by BB 01, 02 BB Group

 


Please Visit My Other Sites: GoldenEyeForever.com | GrandTheftAutoForever.com

Got kids? Check out my Dora The Explorer site with games and coloring pages!

Our forums feature Nintendo 64 games, GoldenEye 007 N64 New Maps and Missions, GoldenEye Cheats, N64 Emulator, Gameshark, GoldenEye Multiplayer and more!

[ Privacy Policy ]