[pypy-svn] r62564 - pypy/trunk/pypy/lang/gameboy

cami at codespeak.net cami at codespeak.net
Thu Mar 5 10:26:45 CET 2009


Author: cami
Date: Thu Mar  5 10:26:42 2009
New Revision: 62564

Modified:
   pypy/trunk/pypy/lang/gameboy/sound.py
Log:
added some comments


Modified: pypy/trunk/pypy/lang/gameboy/sound.py
==============================================================================
--- pypy/trunk/pypy/lang/gameboy/sound.py	(original)
+++ pypy/trunk/pypy/lang/gameboy/sound.py	Thu Mar  5 10:26:42 2009
@@ -4,7 +4,7 @@
 Audio Processor Unit (Sharp LR35902 APU)
 """
 
-from pypy.lang.gameboy import constants
+from pypy.lang.gameboy.constants import *
 from pypy.lang.gameboy.ram import iMemory
 
 class Channel(object):
@@ -20,23 +20,36 @@
         self.envelope  = 0
         self.frequency = 0
         self.playback  = 0
-        self.nr0             = 0
-        self.nr1             = 0
-        self.nr2             = 0
-        self.nr4             = 0
-        self.nr3             = 0
+        self.nr0       = 0
+        self.nr1       = 0
+        self.nr2       = 0
+        self.nr4       = 0
+        self.nr3       = 0
         self.index     = 0
         self.length    = 0
         self.frequency = 0
-        self.enabled         = False
-        #XXX need to push this up into the Sound class
-        self.output_enable  = False
+        self.enabled   = False
         
     def reset(self):
         self.index = 0
         self.set_length(0xFF)
         self.set_playback(0xBF)
     
+    
+    def update_audio(self):
+        self.update_enabled()
+        self.update_envelope_and_volume()
+        self.update_frequency_and_playback()
+        
+    def update_enabled():
+        pass
+        
+    def update_envelope_and_volume():
+        pass
+        
+    def update_frequency_and_playback():
+        
+        
     def get_length(self):
         return self.length
         
@@ -64,12 +77,12 @@
         # Audio Channel 1 int
     def __init__(self, sample_rate, frequency_table):
         Channel.__init__(self, sample_rate, frequency_table)
-        self.sample_sweep            = 0
+        self.sample_sweep    = 0
         self.index           = 0
         self.length          = 0
-        self.volume            = 0
+        self.volume          = 0
         self.envelope_length = 0
-        self.sample_sweep_length     = 0
+        self.sample_sweep_length = 0
         self.frequency       = 0
     
     def reset(self):
@@ -86,12 +99,12 @@
 
     def set_sweep(self, data):
         self.sample_sweep        = data
-        self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \
+        self.sample_sweep_length = (SOUND_CLOCK / 128) * \
                                 ((self.sample_sweep >> 4) & 0x07)
 
     def set_length(self, data):
         self.length   = data
-        self.length = (constants.SOUND_CLOCK / 256) * \
+        self.length = (SOUND_CLOCK / 256) * \
                             (64 - (self.length & 0x3F))
                             
     def set_envelope(self, data):
@@ -108,6 +121,7 @@
 
 
     def set_frequency(self, data):
+        # TODO make sure get and set frequency will work
         self.frequency = data
         index = self.frequency + ((self.playback & 0x07) << 8)
         self.frequency = self.frequency_table[index]
@@ -120,19 +134,13 @@
         if (self.playback & 0x80) != 0:
             self.enabled = True
             if (self.playback & 0x40) != 0 and self.length == 0:
-                self.length = (constants.SOUND_CLOCK / 256) * \
+                self.length = (SOUND_CLOCK / 256) * \
                                     (64 - (self.length & 0x3F))
-            self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \
+            self.sample_sweep_length = (SOUND_CLOCK / 128) * \
                                     ((self.sample_sweep >> 4) & 0x07)
             self.volume = self.envelope >> 4
-            self.envelope_length = (constants.SOUND_CLOCK / 64) * \
+            self.envelope_length = (SOUND_CLOCK / 64) * \
                                         (self.envelope & 0x07)
-                                        
-    def update_audio(self):
-        self.update_enable()
-        self.update_volume_and_envelope()
-        self.update_frequency_and_playback()
-
 
     def update_enable(self):
         if (self.playback & 0x40) != 0 and self.length > 0:
@@ -141,8 +149,7 @@
                 self.enabled = False
                 
     def update_volume_and_envelope(self):
-        if self.envelope_length <= 0:
-            return
+        if self.envelope_length <= 0: return
         self.envelope_length -= 1
         if self.envelope_length <= 0:
             if (self.envelope & 0x08) != 0:
@@ -150,8 +157,7 @@
                     self.volume += 1
             elif self.volume > 0:
                 self.volume -= 1
-            self.envelope_length += (constants.SOUND_CLOCK / 64) * \
-                                         (self.envelope & 0x07)
+            self.envelope_length += (SOUND_CLOCK / 64) * (self.envelope & 0x07)
                                              
     def update_frequency_and_playback(self):
         if self.sample_sweep_length <= 0:
@@ -161,38 +167,41 @@
             return
         sweep_steps = (self.sample_sweep & 0x07)
         if sweep_steps != 0:
-            frequency = ((self.playback & 0x07) << 8) + \
-                        self.frequency
-            if (self.sample_sweep & 0x08) != 0:
-                frequency -= frequency >> sweep_steps
-            else:
-                frequency += frequency >> sweep_steps
-            if frequency < 2048:
-                self.frequency = self.frequency_table[frequency]
-                self.frequency = frequency & 0xFF
-                self.playback = (self.playback & 0xF8) + \
-                                     ((frequency >> 8) & 0x07)
-            else:
-                self.frequency = 0
-                self.output_enable &= ~0x01
-        self.sample_sweep_length += (constants.SOUND_CLOCK / 128) * \
+            self.update_frequency()
+        self.sample_sweep_length += (SOUND_CLOCK / 128) * \
                                  ((self.sample_sweep >> 4) & 0x07)
-                                         
+         
+    def update_frequency(self):
+        frequency = ((self.playback & 0x07) << 8) + self.frequency
+        if (self.sample_sweep & 0x08) != 0:
+            frequency -= frequency >> sweep_steps
+        else:
+            frequency += frequency >> sweep_steps
+        if frequency < 2048:
+            self.frequency = self.frequency_table[frequency]
+            self.frequency = frequency & 0xFF
+            self.playback = (self.playback & 0xF8) + \
+                                 ((frequency >> 8) & 0x07)
+        else:
+            self.frequency = 0
+            self.enabled = False
+            #self.output_enable &= ~0x01
+                
     def mix_audio(self, buffer, length, output_terminal):
         wave_pattern = self.get_current_wave_pattern()
         for index in range(0, length, 3):
             self.index += self.frequency
-            if (self.index & (0x1F << 22)) >= wave_pattern:
+           # if (self.index & (0x1F << 22)) >= wave_pattern:
                 # output_terminal & 0x20 for the second SquareWaveChannel
                 if (output_terminal & 0x10) != 0:
                     buffer[index + 0] -= self.volume
                 if (output_terminal & 0x01) != 0:
                     buffer[index + 1] -= self.volume
-            else:
-                if (output_terminal & 0x10) != 0:
-                    buffer[index + 0] += self.volume
-                if (output_terminal & 0x01) != 0:
-                    buffer[index + 1] += self.volume
+            #else:
+            #    if (output_terminal & 0x10) != 0:
+            #        buffer[index + 0] += self.volume
+            #    if (output_terminal & 0x01) != 0:
+            #        buffer[index + 1] += self.volume
                     
     def get_current_wave_pattern(self):
         wave_pattern = 0x18
@@ -244,7 +253,7 @@
 
     def set_length(self, data):
         self.length = data
-        self.length = (constants.SOUND_CLOCK / 256) * \
+        self.length = (SOUND_CLOCK / 256) * \
                             (256 - self.length)
 
     def set_level(self, data):
@@ -262,7 +271,7 @@
         if (self.playback & 0x80) != 0 and (self.enable & 0x80) != 0:
             self.enabled = True
             if (self.playback & 0x40) != 0 and self.length == 0:
-                self.length = (constants.SOUND_CLOCK / 256) *\
+                self.length = (SOUND_CLOCK / 256) *\
                                     (256 - self.length)
     
     def set_wave_pattern(self, address, data):
@@ -274,8 +283,8 @@
     def update_audio(self):
         if (self.playback & 0x40) != 0 and self.length > 0:
             self.length-=1
-            if self.length <= 0:
-                self.output_enable &= ~0x04
+            self.enabled =  self.length <= 0:
+             #self.output_enable &= ~0x04
 
     def mix_audio(self, buffer, length, output_terminal):
         wave_pattern = self.get_current_wave_pattern()
@@ -337,7 +346,7 @@
             divider = 1
             if ratio != 0:
                 divider = 2 * ratio
-            self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / \
+            self.noiseFreqRatioTable[ratio] = (GAMEBOY_CLOCK / \
                                              divider) *sampleFactor
 
     def generate_noise_tables(self):
@@ -381,7 +390,7 @@
 
     def set_length(self, data):
         self.length = data
-        self.length = (constants.SOUND_CLOCK / 256) * \
+        self.length = (SOUND_CLOCK / 256) * \
                             (64 - (self.length & 0x3F))
 
     def set_envelope(self, data):
@@ -410,23 +419,19 @@
             return
         self.enabled = True
         if (self.playback & 0x40) != 0 and self.length == 0:
-            self.length = (constants.SOUND_CLOCK / 256) * \
+            self.length = (SOUND_CLOCK / 256) * \
                                 (64 - (self.length & 0x3F))
         self.volume = self.envelope >> 4
-        self.envelope_length = (constants.SOUND_CLOCK / 64) * \
+        self.envelope_length = (SOUND_CLOCK / 64) * \
                                     (self.envelope & 0x07)
         self.index = 0
-
-    def update_audio(self):
-        self.update_enabled()
-        self.update_envelope_and_volume()
     
     def update_enabled(self):
         if (self.playback & 0x40) != 0 and self.length > 0:
             self.length-=1
-            if self.length <= 0:
-                self.output_enable &= ~0x08
-        
+            self.enabled =  self.length <= 0:
+            #self.output_enable &= ~0x08
+                
     def update_envelope_and_volume(self):
         if self.envelope_length <= 0:
             return
@@ -438,7 +443,7 @@
                 self.volume+=1
         elif self.volume > 0:
             self.volume-=1
-        self.envelope_length += (constants.SOUND_CLOCK / 64) *\
+        self.envelope_length += (SOUND_CLOCK / 64) *\
                                      (self.envelope & 0x07)
                                          
     def mix_audio(self, buffer, length, output_terminal):
@@ -492,13 +497,14 @@
         self.channel2 = SquareWaveChannel(self.sample_rate, self.frequency_table)
         self.channel3 = VoluntaryWaveChannel(self.sample_rate, self.frequency_table)
         self.channel4 = NoiseGenerator(self.sample_rate, self.frequency_table)
+        self.channels = [self.channel1, self.channel2, self.channel3, self.channel4]
         
         
     def generate_frequency_table(self):
         self.frequency_table = [0] * 2048
          # frequency = (4194304 / 32) / (2048 - period) Hz
         for period in range(0, 2048):
-            skip = (((constants.GAMEBOY_CLOCK << 10) / \
+            skip = (((GAMEBOY_CLOCK << 10) / \
                    self.sample_rate) << 16) / (2048 - period)
             if skip >= (32 << 22):
                 self.frequency_table[period] = 0
@@ -506,7 +512,7 @@
                 self.frequency_table[period] = skip
 
     def reset(self):
-        self.cycles = int(constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK)
+        self.cycles = int(GAMEBOY_CLOCK / SOUND_CLOCK)
         self.frames = 0
         self.channel1.reset()
         self.channel2.reset()
@@ -539,145 +545,136 @@
             self.update_audio()
             if self.driver.is_enabled():
                 self.mix_down_audio()
-            self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK
+            self.cycles += GAMEBOY_CLOCK / SOUND_CLOCK
             
     def mix_down_audio(self):
         self.frames += self.driver.get_sample_rate()
-        length      = (self.frames / constants.SOUND_CLOCK) << 1
+        length      = (self.frames / SOUND_CLOCK) << 1
         self.mix_audio(self.buffer, length)
         self.driver.write(self.buffer, length)
-        self.frames %= constants.SOUND_CLOCK
+        self.frames %= SOUND_CLOCK
         
     def read(self, address):
+        # TODO map the read/write in groups directly to the channels
         address = int(address)
-        if address==constants.NR10:
+        if address==NR10:
             return self.channel1.get_sweep()
-        elif address == constants.NR11:
+        elif address == NR11:
             return self.channel1.get_length()
-        elif address == constants.NR12:
+        elif address == NR12:
             return self.channel1.get_envelope()
-        elif address == constants.NR13:
+        elif address == NR13:
             return self.channel1.get_frequency()
-        elif address == constants.NR14:
+        elif address == NR14:
             return self.channel1.get_playback()
 
-        elif address == constants.NR21:
+        elif address == NR21:
             return self.channel2.get_length()
-        elif address == constants.NR22:
+        elif address == NR22:
             return self.channel2.get_envelope()
-        elif address==constants.NR23:
+        elif address==NR23:
             return self.channel2.get_frequency()
-        elif address==constants.NR24:
+        elif address==NR24:
             return self.channel2.get_playback()
 
-        elif address==constants.NR30:
+        elif address==NR30:
             return self.channel3.get_enable()
-        elif address==constants.NR31:
+        elif address==NR31:
             return self.channel3.get_length()
-        elif address==constants.NR32:
+        elif address==NR32:
             return self.channel3.get_level()
-        elif address==constants.NR33:
+        elif address==NR33:
             return self.channel4.get_frequency()
-        elif address==constants.NR34:
+        elif address==NR34:
             return self.channel3.get_playback()
 
-        elif address==constants.NR41:
+        elif address==NR41:
             return self.channel4.get_length()
-        elif address==constants.NR42:
+        elif address==NR42:
             return self.channel4.get_envelope()
-        elif address==constants.NR43:
+        elif address==NR43:
             return self.channel4.get_polynomial()
-        elif address==constants.NR44:
+        elif address==NR44:
             return self.channel4.get_playback()
 
-        elif address==constants.NR50:
+        elif address==NR50:
             return self.get_output_level()
-        elif address==constants.NR51:
+        elif address==NR51:
             return self.get_output_terminal()
-        elif address==constants.NR52:
+        elif address==NR52:
             return self.get_output_enable()
 
-        elif address >= constants.AUD3WAVERAM and \
-             address <= constants.AUD3WAVERAM + 0x3F:
+        elif address >= AUD3WAVERAM and \
+             address <= AUD3WAVERAM + 0x3F:
             return self.channel3.get_wave_pattern(address)
         return 0xFF
 
     def write(self, address, data):
         address = int(address)
-        if address==constants.NR10:
+        if address == NR10:
             self.channel1.set_sweep(data)
-        elif address == constants.NR11:
+        elif address == NR11:
             self.channel1.set_length(data)
-        elif address == constants.NR12:
+        elif address == NR12:
             self.channel1.set_envelope(data)
-        elif address == constants.NR13:
+        elif address == NR13:
             self.channel1.set_frequency(data)
-        elif address == constants.NR14:
+        elif address == NR14:
             self.channel1.set_playback(data)
         
-        elif address == constants.NR21:
+        elif address == NR21:
             self.channel2.set_length(data)
-        elif address == constants.NR22:
+        elif address == NR22:
             self.channel2.set_envelope(data)
-        elif address == constants.NR23:
+        elif address == NR23:
             self.channel2.set_frequency(data)
-        elif address == constants.NR24:
+        elif address == NR24:
             self.channel2.set_playback(data)
         
-        elif address == constants.NR30:
+        elif address == NR30:
             self.channel3.set_enable(data)
-        elif address == constants.NR31:
+        elif address == NR31:
             self.channel3.set_length(data)
-        elif address == constants.NR32:
+        elif address == NR32:
             self.channel3.set_level(data)
-        elif address == constants.NR33:
+        elif address == NR33:
             self.channel3.set_frequency(data)
-        elif address == constants.NR34:
+        elif address == NR34:
             self.channel3.set_playback(data)
         
-        elif address == constants.NR41:
+        elif address == NR41:
             self.channel4.set_length(data)
-        elif address == constants.NR42:
+        elif address == NR42:
             self.channel4.set_envelope(data)
-        elif address == constants.NR43:
+        elif address == NR43:
             self.channel4.set_polynomial(data)
-        elif address == constants.NR44:
+        elif address == NR44:
             self.channel4.set_playback(data)
         
-        elif address == constants.NR50:
+        elif address == NR50:
             self.set_output_level(data)
-        elif address == constants.NR51:
+        elif address == NR51:
             self.set_output_terminal(data)
-        elif address == constants.NR52:
+        elif address == NR52:
             self.set_output_enable(data)
         
-        elif address >= constants.AUD3WAVERAM and \
-             address <= constants.AUD3WAVERAM + 0x3F:
+        elif address >= AUD3WAVERAM and \
+             address <= AUD3WAVERAM + 0x3F:
             self.channel3.set_wave_pattern(address, data)
 
     def update_audio(self):
         if (self.output_enable & 0x80) == 0:
             return
-        if (self.output_enable & 0x01) != 0:
-            self.channel1.update_audio()
-        if (self.output_enable & 0x02) != 0:
-            self.channel2.update_audio()
-        if (self.output_enable & 0x04) != 0:
-            self.channel3.update_audio()
-        if (self.output_enable & 0x08) != 0:
-            self.channel4.update_audio()
+        for channel in self.channels
+            if channel.enabled:
+                channel.update_audio()
 
     def mix_audio(self, buffer, length):
         if (self.output_enable & 0x80) == 0:
             return
-        if (self.output_enable & 0x01) != 0:
-            self.channel1.mix_audio(buffer, length, self.output_terminal)
-        if (self.output_enable & 0x02) != 0:
-            self.channel2.mix_audio(buffer, length, self.output_terminal)
-        if (self.output_enable & 0x04) != 0:
-            self.channel3.mix_audio(buffer, length, self.output_terminal)
-        if (self.output_enable & 0x08) != 0:
-            self.channel4.mix_audio(buffer, length, self.output_terminal)
+        for channel in self.channels
+            if channel.enabled:
+                channel.mix_audio(buffer, length, self.output_terminal)
 
      # Output Control
     def get_output_level(self):
@@ -696,6 +693,7 @@
         self.output_terminal = data
 
     def set_output_enable(self, data):
+        # TODO map directly to the channels
         self.output_enable = (self.output_enable & 0x7F) | (data & 0x80)
         if (self.output_enable & 0x80) == 0x00:
             self.output_enable &= 0xF0



More information about the Pypy-commit mailing list