Rip PCM samples from Roms?

Discussion of programming and development for the original Game Boy and Game Boy Color.
Post Reply
catsup
Posts: 4
Joined: Sat Jul 03, 2010 1:29 pm

Rip PCM samples from Roms?

Post by catsup » Sat Jul 03, 2010 1:57 pm

Hello!

First post! Long time lurker and noob. I'm curious if theres any software out there that extracts samples from game boy roms?

The way Ive done it is that Ive imported the rom as raw audio into an audio editor (sony sound forge, audacity etc..) and located the samples.
The downside is that I'm not sure how to determine what sample rate the samples are supposed to be in. I usually set it to somewhere between 4000Hz - 8000Hz and 8-bit unsigned.

It doesn't work that well with all games, often the samples sound extremely bad and almost unrecognizable.


Anyone have any ideas?

Thanks in advance!

// catsup

tepples
Posts: 22055
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Sat Jul 03, 2010 2:00 pm

Game Boy waveforms are 4-bit unsigned, big endian within each nibble, and usually 16 bytes (32 samples) long. A couple old NES games used this same format, for which I made a ripper a long time ago when REing Skate or Die 2.

User avatar
Dwedit
Posts: 4356
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Post by Dwedit » Sat Jul 03, 2010 2:00 pm

You can always try decoding the entire rom as a series of 4-bit samples, and seeing if it sounds any better. (upper 4 bits first)
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

catsup
Posts: 4
Joined: Sat Jul 03, 2010 1:29 pm

Post by catsup » Sat Jul 03, 2010 2:35 pm

Thanks for your quick response!

The reason I'm setting it to 8-bits is that sound forge doesn't seem to go any lower.
tepples wrote:A couple old NES games used this same format, for which I made a ripper a long time ago when REing Skate or Die 2.
Stupid question maybe but is this ripper exclusively for NES games or would it work with any file containing that specific data?

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg » Sat Jul 03, 2010 3:13 pm

If you treat the ROM as an 8-bit unsigned sample, you'll be able to hear any 4-bit samples just fine. You'll miss every other sample, but that just has the effect of halving the sampling rate. Try playing it at 44.1 kHz to locate samples, then experiment with lower rates for each sample you find. Once you do that, you can do some more advanced extraction to get the missing samples that treating it as 8-bit skips.

tepples
Posts: 22055
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Sat Jul 03, 2010 4:13 pm

catsup wrote:Stupid question maybe but is this ripper exclusively for NES games or would it work with any file containing that specific data?
It decodes all the nibbles in a whole file to one big .wav file. Want it?

catsup
Posts: 4
Joined: Sat Jul 03, 2010 1:29 pm

Post by catsup » Sat Jul 03, 2010 4:51 pm

tepples wrote:
catsup wrote:Stupid question maybe but is this ripper exclusively for NES games or would it work with any file containing that specific data?
It decodes all the nibbles in a whole file to one big .wav file. Want it?
Yes please! :D

tepples
Posts: 22055
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Sat Jul 03, 2010 5:30 pm

System requirements: 2.6 snakes on a plane
Save the following as nibbledecode.py

Code: Select all

#!/usr/bin/env python
"""

nibbledecode
Use this to convert the samples in e.g. Skate or Die 2 for NES or
any of several Game Boy games to wave format for other apps to use.

In Windows, save it as nibbledecode.py and drag raw files onto it.

Limitations: Master System/Game Gear nonlinear samples are not
supported.

(See copyright notice in versionMsg below.)


"""
from __future__ import with_statement, division
from contextlib import closing

usageMsg = "usage: %prog [options] infile.4bl [outfile.wav]"
descriptionMsg = """Expands 4-bit-per-sample linear PCM to an 8-bit wave file."""
versionMsg = """%prog 0.01
Copyright 2010 Damian Yerrick
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.  This file is offered as-is,
without any warranty.
"""

def expand4bit(src, little=False, signed=False):
    import array
    dst = array.array('B')
    xorData = 0x88 if signed else 0x08
    for byte in src:
        byte = ord(byte)
        s1 = (byte & 0xF0)
        s2 = (byte & 0x0F) << 4
        if little:
            s2, s1 = s1, s2
        dst.append(s1 ^ xorData)
        dst.append(s2 ^ xorData)
    return dst.tostring()

def main(argv=None):
    from optparse import OptionParser
    import wave

    if argv is None:
        import sys
        argv = sys.argv
    
    parser = OptionParser(usage=usageMsg, description=descriptionMsg,
                          version=versionMsg)
    parser.add_option('-l', '--little', dest='little',
                      default=False, action='store_true',
                      help='use low nibble first')
    parser.add_option('-s', '--signed', dest='signed',
                      default=False, action='store_true',
                      help='decode samples as signed nibbles')
    (options, args) = parser.parse_args(argv[1:])
    if len(args) not in (1, 2):
        parser.error("wrong number of arguments; try with --help")

    with open(args[0], 'rb') as infp:
        data = infp.read()
    data = expand4bit(data, little=options.little, signed=options.signed)
    outfilename = args[1] if len(args) > 1 else args[0] + '.wav'
    with closing(wave.open(outfilename, 'wb')) as outfp:
        outfp.setnchannels(1)
        outfp.setframerate(8372)
        outfp.setsampwidth(1)
        outfp.writeframes(data)

if __name__=='__main__':
    main()

catsup
Posts: 4
Joined: Sat Jul 03, 2010 1:29 pm

Post by catsup » Sat Jul 03, 2010 9:26 pm

tepples you're my hero. It worked great! Thanks!

strat
Posts: 370
Joined: Mon Apr 07, 2008 6:08 pm
Location: Missouri

Post by strat » Thu Jul 15, 2010 8:33 pm

Hate to be a pain but I tried the script with Skate or Die 2 and all I heard was a "Skate or Die" voice over. Are you supposed to hear the whole title music that way?

User avatar
Jeroen
Posts: 1036
Joined: Tue Jul 03, 2007 1:49 pm

Post by Jeroen » Thu Jul 15, 2010 8:41 pm

I think it rips JUST the samples. Not all the music.

strat
Posts: 370
Joined: Mon Apr 07, 2008 6:08 pm
Location: Missouri

Post by strat » Thu Jul 15, 2010 8:53 pm

Oh. I thought the whole title music was a sample.

User avatar
Jeroen
Posts: 1036
Joined: Tue Jul 03, 2007 1:49 pm

Post by Jeroen » Thu Jul 15, 2010 9:04 pm

iirc it is.....but they backed it using some fancy code to make it all musical.

Post Reply