Commits

spencercw committed c67f7d7

Refactor sound channel 1.

  • Participants
  • Parent commits e3f98e3

Comments (0)

Files changed (6)

gb_emulator/gb.pb.cc

       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(GbSoundData));
   GbSoundData_Sound1_descriptor_ = GbSoundData_descriptor_->nested_type(0);
-  static const int GbSoundData_Sound1_offsets_[12] = {
+  static const int GbSoundData_Sound1_offsets_[15] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, gb_frequency_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, act_frequency_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, hi_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, duty_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, duration_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, countdown_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, sweep_enabled_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, sweep_shifts_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, sweep_type_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, sweep_step_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, sweep_countdown_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, envelope_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, envelope_direction_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, envelope_step_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GbSoundData_Sound1, envelope_countdown_),
   };
     "(\r\022\014\n\004cart\030\010 \002(\r\022\026\n\016ext_ram_enable\030\t \002(\010"
     "\022\020\n\010rom_bank\030\n \002(\r\022\020\n\010ram_bank\030\013 \002(\r\022\024\n\014"
     "ext_ram_bank\030\014 \002(\r\022\021\n\tvram_bank\030\r \002(\r\022\013\n"
-    "\003mbc\030\016 \002(\014\022\013\n\003rtc\030\017 \002(\014\"\201\010\n\013GbSoundData\022"
+    "\003mbc\030\016 \002(\014\022\013\n\003rtc\030\017 \002(\014\"\306\010\n\013GbSoundData\022"
     "\025\n\rexcess_cycles\030\001 \002(\001\022$\n\007sound_1\030\002 \002(\0132"
     "\023.GbSoundData.Sound1\022$\n\007sound_2\030\003 \002(\0132\023."
     "GbSoundData.Sound2\022$\n\007sound_3\030\004 \002(\0132\023.Gb"
     "SoundData.Sound3\022$\n\007sound_4\030\005 \002(\0132\023.GbSo"
-    "undData.Sound4\032\376\001\n\006Sound1\022\024\n\014gb_frequenc"
-    "y\030\001 \002(\001\022\025\n\ract_frequency\030\002 \002(\001\022\n\n\002hi\030\003 \002"
-    "(\010\022\014\n\004duty\030\004 \002(\001\022\021\n\tcountdown\030\005 \002(\001\022\024\n\014s"
-    "weep_shifts\030\006 \002(\r\022\022\n\nsweep_type\030\007 \002(\010\022\022\n"
-    "\nsweep_step\030\010 \002(\001\022\027\n\017sweep_countdown\030\t \002"
-    "(\001\022\020\n\010envelope\030\n \002(\r\022\025\n\renvelope_step\030\013 "
-    "\002(\001\022\032\n\022envelope_countdown\030\014 \002(\001\032\325\001\n\006Soun"
-    "d2\022\024\n\014gb_frequency\030\001 \002(\001\022\025\n\ract_frequenc"
-    "y\030\002 \002(\001\022\n\n\002hi\030\003 \002(\010\022\014\n\004duty\030\004 \002(\001\022\020\n\010dur"
-    "ation\030\005 \002(\001\022\021\n\tcountdown\030\006 \002(\001\022\020\n\010envelo"
-    "pe\030\007 \002(\r\022\032\n\022envelope_direction\030\010 \002(\010\022\025\n\r"
-    "envelope_step\030\t \002(\001\022\032\n\022envelope_countdow"
-    "n\030\n \002(\001\032\227\001\n\006Sound3\022\024\n\014gb_frequency\030\001 \002(\001"
-    "\022\025\n\ract_frequency\030\002 \002(\001\022\020\n\010duration\030\003 \002("
-    "\001\022\021\n\tcountdown\030\004 \002(\001\022\022\n\nwave_index\030\005 \002(\r"
-    "\022\021\n\tout_level\030\006 \002(\r\022\024\n\014wave_pattern\030\007 \002("
-    "\014\032\317\001\n\006Sound4\022\021\n\tfrequency\030\001 \002(\001\022\020\n\010durat"
-    "ion\030\002 \002(\001\022\021\n\tcountdown\030\003 \002(\001\022\020\n\010envelope"
-    "\030\004 \002(\r\022\032\n\022envelope_direction\030\005 \002(\010\022\025\n\ren"
-    "velope_step\030\006 \002(\001\022\032\n\022envelope_countdown\030"
-    "\007 \002(\001\022\025\n\rcounter_steps\030\010 \002(\010\022\025\n\rcounter_"
-    "index\030\t \002(\r\"\272\001\n\013GbVideoData\022\024\n\014priority_"
-    "map\030\001 \002(\014\022\026\n\016gbc_bg_palette\030\002 \002(\014\022\032\n\022gbc"
-    "_sprite_palette\030\003 \002(\014\022\025\n\rhblank_cycles\030\004"
-    " \002(\r\022\027\n\017oam_read_cycles\030\005 \002(\r\022\034\n\024oam_vra"
-    "m_read_cycles\030\006 \002(\r\022\023\n\013line_cycles\030\007 \002(\r"
-    "\"\274\001\n\006GbData\022\013\n\003rom\030\001 \002(\t\022\020\n\010rom_size\030\002 \002"
-    "(\r\022\024\n\014rom_checksum\030\003 \002(\r\022\013\n\003gbc\030\004 \002(\010\022\027\n"
-    "\003cpu\030\005 \002(\0132\n.GbCpuData\022\035\n\006memory\030\006 \002(\0132\r"
-    ".GbMemoryData\022\033\n\005sound\030\007 \002(\0132\014.GbSoundDa"
-    "ta\022\033\n\005video\030\010 \002(\0132\014.GbVideoData", 1791);
+    "undData.Sound4\032\303\002\n\006Sound1\022\024\n\014gb_frequenc"
+    "y\030\001 \002(\r\022\025\n\ract_frequency\030\002 \002(\001\022\n\n\002hi\030\003 \002"
+    "(\010\022\014\n\004duty\030\004 \002(\001\022\020\n\010duration\030\005 \002(\001\022\021\n\tco"
+    "untdown\030\006 \002(\001\022\025\n\rsweep_enabled\030\007 \002(\010\022\024\n\014"
+    "sweep_shifts\030\010 \002(\r\022\022\n\nsweep_type\030\t \002(\010\022\022"
+    "\n\nsweep_step\030\n \002(\001\022\027\n\017sweep_countdown\030\013 "
+    "\002(\001\022\020\n\010envelope\030\014 \002(\r\022\032\n\022envelope_direct"
+    "ion\030\r \002(\010\022\025\n\renvelope_step\030\016 \002(\001\022\032\n\022enve"
+    "lope_countdown\030\017 \002(\001\032\325\001\n\006Sound2\022\024\n\014gb_fr"
+    "equency\030\001 \002(\r\022\025\n\ract_frequency\030\002 \002(\001\022\n\n\002"
+    "hi\030\003 \002(\010\022\014\n\004duty\030\004 \002(\001\022\020\n\010duration\030\005 \002(\001"
+    "\022\021\n\tcountdown\030\006 \002(\001\022\020\n\010envelope\030\007 \002(\r\022\032\n"
+    "\022envelope_direction\030\010 \002(\010\022\025\n\renvelope_st"
+    "ep\030\t \002(\001\022\032\n\022envelope_countdown\030\n \002(\001\032\227\001\n"
+    "\006Sound3\022\024\n\014gb_frequency\030\001 \002(\r\022\025\n\ract_fre"
+    "quency\030\002 \002(\001\022\020\n\010duration\030\003 \002(\001\022\021\n\tcountd"
+    "own\030\004 \002(\001\022\022\n\nwave_index\030\005 \002(\r\022\021\n\tout_lev"
+    "el\030\006 \002(\r\022\024\n\014wave_pattern\030\007 \002(\014\032\317\001\n\006Sound"
+    "4\022\021\n\tfrequency\030\001 \002(\001\022\020\n\010duration\030\002 \002(\001\022\021"
+    "\n\tcountdown\030\003 \002(\001\022\020\n\010envelope\030\004 \002(\r\022\032\n\022e"
+    "nvelope_direction\030\005 \002(\010\022\025\n\renvelope_step"
+    "\030\006 \002(\001\022\032\n\022envelope_countdown\030\007 \002(\001\022\025\n\rco"
+    "unter_steps\030\010 \002(\010\022\025\n\rcounter_index\030\t \002(\r"
+    "\"\272\001\n\013GbVideoData\022\024\n\014priority_map\030\001 \002(\014\022\026"
+    "\n\016gbc_bg_palette\030\002 \002(\014\022\032\n\022gbc_sprite_pal"
+    "ette\030\003 \002(\014\022\025\n\rhblank_cycles\030\004 \002(\r\022\027\n\017oam"
+    "_read_cycles\030\005 \002(\r\022\034\n\024oam_vram_read_cycl"
+    "es\030\006 \002(\r\022\023\n\013line_cycles\030\007 \002(\r\"\274\001\n\006GbData"
+    "\022\013\n\003rom\030\001 \002(\t\022\020\n\010rom_size\030\002 \002(\r\022\024\n\014rom_c"
+    "hecksum\030\003 \002(\r\022\013\n\003gbc\030\004 \002(\010\022\027\n\003cpu\030\005 \002(\0132"
+    "\n.GbCpuData\022\035\n\006memory\030\006 \002(\0132\r.GbMemoryDa"
+    "ta\022\033\n\005sound\030\007 \002(\0132\014.GbSoundData\022\033\n\005video"
+    "\030\010 \002(\0132\014.GbVideoData", 1860);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "gb.proto", &protobuf_RegisterTypes);
   GbCpuData::default_instance_ = new GbCpuData();
 const int GbSoundData_Sound1::kActFrequencyFieldNumber;
 const int GbSoundData_Sound1::kHiFieldNumber;
 const int GbSoundData_Sound1::kDutyFieldNumber;
+const int GbSoundData_Sound1::kDurationFieldNumber;
 const int GbSoundData_Sound1::kCountdownFieldNumber;
+const int GbSoundData_Sound1::kSweepEnabledFieldNumber;
 const int GbSoundData_Sound1::kSweepShiftsFieldNumber;
 const int GbSoundData_Sound1::kSweepTypeFieldNumber;
 const int GbSoundData_Sound1::kSweepStepFieldNumber;
 const int GbSoundData_Sound1::kSweepCountdownFieldNumber;
 const int GbSoundData_Sound1::kEnvelopeFieldNumber;
+const int GbSoundData_Sound1::kEnvelopeDirectionFieldNumber;
 const int GbSoundData_Sound1::kEnvelopeStepFieldNumber;
 const int GbSoundData_Sound1::kEnvelopeCountdownFieldNumber;
 #endif  // !_MSC_VER
 
 void GbSoundData_Sound1::SharedCtor() {
   _cached_size_ = 0;
-  gb_frequency_ = 0;
+  gb_frequency_ = 0u;
   act_frequency_ = 0;
   hi_ = false;
   duty_ = 0;
+  duration_ = 0;
   countdown_ = 0;
+  sweep_enabled_ = false;
   sweep_shifts_ = 0u;
   sweep_type_ = false;
   sweep_step_ = 0;
   sweep_countdown_ = 0;
   envelope_ = 0u;
+  envelope_direction_ = false;
   envelope_step_ = 0;
   envelope_countdown_ = 0;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 
 void GbSoundData_Sound1::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    gb_frequency_ = 0;
+    gb_frequency_ = 0u;
     act_frequency_ = 0;
     hi_ = false;
     duty_ = 0;
+    duration_ = 0;
     countdown_ = 0;
+    sweep_enabled_ = false;
     sweep_shifts_ = 0u;
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     sweep_type_ = false;
     sweep_step_ = 0;
-  }
-  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     sweep_countdown_ = 0;
     envelope_ = 0u;
+    envelope_direction_ = false;
     envelope_step_ = 0;
     envelope_countdown_ = 0;
   }
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
     switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // required double gb_frequency = 1;
+      // required uint32 gb_frequency = 1;
       case 1: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
                  input, &gb_frequency_)));
           set_has_gb_frequency();
         } else {
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(41)) goto parse_countdown;
+        if (input->ExpectTag(41)) goto parse_duration;
         break;
       }
       
-      // required double countdown = 5;
+      // required double duration = 5;
       case 5: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
+         parse_duration:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+                 input, &duration_)));
+          set_has_duration();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(49)) goto parse_countdown;
+        break;
+      }
+      
+      // required double countdown = 6;
+      case 6: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
          parse_countdown:
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(48)) goto parse_sweep_shifts;
+        if (input->ExpectTag(56)) goto parse_sweep_enabled;
         break;
       }
       
-      // required uint32 sweep_shifts = 6;
-      case 6: {
+      // required bool sweep_enabled = 7;
+      case 7: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_sweep_enabled:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &sweep_enabled_)));
+          set_has_sweep_enabled();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(64)) goto parse_sweep_shifts;
+        break;
+      }
+      
+      // required uint32 sweep_shifts = 8;
+      case 8: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
          parse_sweep_shifts:
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(56)) goto parse_sweep_type;
+        if (input->ExpectTag(72)) goto parse_sweep_type;
         break;
       }
       
-      // required bool sweep_type = 7;
-      case 7: {
+      // required bool sweep_type = 9;
+      case 9: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
          parse_sweep_type:
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(65)) goto parse_sweep_step;
+        if (input->ExpectTag(81)) goto parse_sweep_step;
         break;
       }
       
-      // required double sweep_step = 8;
-      case 8: {
+      // required double sweep_step = 10;
+      case 10: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
          parse_sweep_step:
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(73)) goto parse_sweep_countdown;
+        if (input->ExpectTag(89)) goto parse_sweep_countdown;
         break;
       }
       
-      // required double sweep_countdown = 9;
-      case 9: {
+      // required double sweep_countdown = 11;
+      case 11: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
          parse_sweep_countdown:
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(80)) goto parse_envelope;
+        if (input->ExpectTag(96)) goto parse_envelope;
         break;
       }
       
-      // required uint32 envelope = 10;
-      case 10: {
+      // required uint32 envelope = 12;
+      case 12: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
          parse_envelope:
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(89)) goto parse_envelope_step;
+        if (input->ExpectTag(104)) goto parse_envelope_direction;
         break;
       }
       
-      // required double envelope_step = 11;
-      case 11: {
+      // required bool envelope_direction = 13;
+      case 13: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_envelope_direction:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &envelope_direction_)));
+          set_has_envelope_direction();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(113)) goto parse_envelope_step;
+        break;
+      }
+      
+      // required double envelope_step = 14;
+      case 14: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
          parse_envelope_step:
         } else {
           goto handle_uninterpreted;
         }
-        if (input->ExpectTag(97)) goto parse_envelope_countdown;
+        if (input->ExpectTag(121)) goto parse_envelope_countdown;
         break;
       }
       
-      // required double envelope_countdown = 12;
-      case 12: {
+      // required double envelope_countdown = 15;
+      case 15: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
             ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
          parse_envelope_countdown:
 
 void GbSoundData_Sound1::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   if (has_gb_frequency()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->gb_frequency(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->gb_frequency(), output);
   }
   
   // required double act_frequency = 2;
     ::google::protobuf::internal::WireFormatLite::WriteDouble(4, this->duty(), output);
   }
   
-  // required double countdown = 5;
+  // required double duration = 5;
+  if (has_duration()) {
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(5, this->duration(), output);
+  }
+  
+  // required double countdown = 6;
   if (has_countdown()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(5, this->countdown(), output);
-  }
-  
-  // required uint32 sweep_shifts = 6;
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->countdown(), output);
+  }
+  
+  // required bool sweep_enabled = 7;
+  if (has_sweep_enabled()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(7, this->sweep_enabled(), output);
+  }
+  
+  // required uint32 sweep_shifts = 8;
   if (has_sweep_shifts()) {
-    ::google::protobuf::internal::WireFormatLite::WriteUInt32(6, this->sweep_shifts(), output);
-  }
-  
-  // required bool sweep_type = 7;
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(8, this->sweep_shifts(), output);
+  }
+  
+  // required bool sweep_type = 9;
   if (has_sweep_type()) {
-    ::google::protobuf::internal::WireFormatLite::WriteBool(7, this->sweep_type(), output);
-  }
-  
-  // required double sweep_step = 8;
+    ::google::protobuf::internal::WireFormatLite::WriteBool(9, this->sweep_type(), output);
+  }
+  
+  // required double sweep_step = 10;
   if (has_sweep_step()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(8, this->sweep_step(), output);
-  }
-  
-  // required double sweep_countdown = 9;
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(10, this->sweep_step(), output);
+  }
+  
+  // required double sweep_countdown = 11;
   if (has_sweep_countdown()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(9, this->sweep_countdown(), output);
-  }
-  
-  // required uint32 envelope = 10;
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(11, this->sweep_countdown(), output);
+  }
+  
+  // required uint32 envelope = 12;
   if (has_envelope()) {
-    ::google::protobuf::internal::WireFormatLite::WriteUInt32(10, this->envelope(), output);
-  }
-  
-  // required double envelope_step = 11;
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(12, this->envelope(), output);
+  }
+  
+  // required bool envelope_direction = 13;
+  if (has_envelope_direction()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(13, this->envelope_direction(), output);
+  }
+  
+  // required double envelope_step = 14;
   if (has_envelope_step()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(11, this->envelope_step(), output);
-  }
-  
-  // required double envelope_countdown = 12;
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(14, this->envelope_step(), output);
+  }
+  
+  // required double envelope_countdown = 15;
   if (has_envelope_countdown()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(12, this->envelope_countdown(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteDouble(15, this->envelope_countdown(), output);
   }
   
   if (!unknown_fields().empty()) {
 
 ::google::protobuf::uint8* GbSoundData_Sound1::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   if (has_gb_frequency()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->gb_frequency(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->gb_frequency(), target);
   }
   
   // required double act_frequency = 2;
     target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(4, this->duty(), target);
   }
   
-  // required double countdown = 5;
+  // required double duration = 5;
+  if (has_duration()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(5, this->duration(), target);
+  }
+  
+  // required double countdown = 6;
   if (has_countdown()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(5, this->countdown(), target);
-  }
-  
-  // required uint32 sweep_shifts = 6;
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->countdown(), target);
+  }
+  
+  // required bool sweep_enabled = 7;
+  if (has_sweep_enabled()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(7, this->sweep_enabled(), target);
+  }
+  
+  // required uint32 sweep_shifts = 8;
   if (has_sweep_shifts()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(6, this->sweep_shifts(), target);
-  }
-  
-  // required bool sweep_type = 7;
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(8, this->sweep_shifts(), target);
+  }
+  
+  // required bool sweep_type = 9;
   if (has_sweep_type()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(7, this->sweep_type(), target);
-  }
-  
-  // required double sweep_step = 8;
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(9, this->sweep_type(), target);
+  }
+  
+  // required double sweep_step = 10;
   if (has_sweep_step()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(8, this->sweep_step(), target);
-  }
-  
-  // required double sweep_countdown = 9;
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(10, this->sweep_step(), target);
+  }
+  
+  // required double sweep_countdown = 11;
   if (has_sweep_countdown()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(9, this->sweep_countdown(), target);
-  }
-  
-  // required uint32 envelope = 10;
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(11, this->sweep_countdown(), target);
+  }
+  
+  // required uint32 envelope = 12;
   if (has_envelope()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(10, this->envelope(), target);
-  }
-  
-  // required double envelope_step = 11;
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(12, this->envelope(), target);
+  }
+  
+  // required bool envelope_direction = 13;
+  if (has_envelope_direction()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(13, this->envelope_direction(), target);
+  }
+  
+  // required double envelope_step = 14;
   if (has_envelope_step()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(11, this->envelope_step(), target);
-  }
-  
-  // required double envelope_countdown = 12;
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(14, this->envelope_step(), target);
+  }
+  
+  // required double envelope_countdown = 15;
   if (has_envelope_countdown()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(12, this->envelope_countdown(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(15, this->envelope_countdown(), target);
   }
   
   if (!unknown_fields().empty()) {
   int total_size = 0;
   
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    // required double gb_frequency = 1;
+    // required uint32 gb_frequency = 1;
     if (has_gb_frequency()) {
-      total_size += 1 + 8;
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->gb_frequency());
     }
     
     // required double act_frequency = 2;
       total_size += 1 + 8;
     }
     
-    // required double countdown = 5;
+    // required double duration = 5;
+    if (has_duration()) {
+      total_size += 1 + 8;
+    }
+    
+    // required double countdown = 6;
     if (has_countdown()) {
       total_size += 1 + 8;
     }
     
-    // required uint32 sweep_shifts = 6;
+    // required bool sweep_enabled = 7;
+    if (has_sweep_enabled()) {
+      total_size += 1 + 1;
+    }
+    
+    // required uint32 sweep_shifts = 8;
     if (has_sweep_shifts()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::UInt32Size(
           this->sweep_shifts());
     }
     
-    // required bool sweep_type = 7;
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // required bool sweep_type = 9;
     if (has_sweep_type()) {
       total_size += 1 + 1;
     }
     
-    // required double sweep_step = 8;
+    // required double sweep_step = 10;
     if (has_sweep_step()) {
       total_size += 1 + 8;
     }
     
-  }
-  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
-    // required double sweep_countdown = 9;
+    // required double sweep_countdown = 11;
     if (has_sweep_countdown()) {
       total_size += 1 + 8;
     }
     
-    // required uint32 envelope = 10;
+    // required uint32 envelope = 12;
     if (has_envelope()) {
       total_size += 1 +
         ::google::protobuf::internal::WireFormatLite::UInt32Size(
           this->envelope());
     }
     
-    // required double envelope_step = 11;
+    // required bool envelope_direction = 13;
+    if (has_envelope_direction()) {
+      total_size += 1 + 1;
+    }
+    
+    // required double envelope_step = 14;
     if (has_envelope_step()) {
       total_size += 1 + 8;
     }
     
-    // required double envelope_countdown = 12;
+    // required double envelope_countdown = 15;
     if (has_envelope_countdown()) {
       total_size += 1 + 8;
     }
     if (from.has_duty()) {
       set_duty(from.duty());
     }
+    if (from.has_duration()) {
+      set_duration(from.duration());
+    }
     if (from.has_countdown()) {
       set_countdown(from.countdown());
     }
+    if (from.has_sweep_enabled()) {
+      set_sweep_enabled(from.sweep_enabled());
+    }
     if (from.has_sweep_shifts()) {
       set_sweep_shifts(from.sweep_shifts());
     }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     if (from.has_sweep_type()) {
       set_sweep_type(from.sweep_type());
     }
     if (from.has_sweep_step()) {
       set_sweep_step(from.sweep_step());
     }
-  }
-  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
     if (from.has_sweep_countdown()) {
       set_sweep_countdown(from.sweep_countdown());
     }
     if (from.has_envelope()) {
       set_envelope(from.envelope());
     }
+    if (from.has_envelope_direction()) {
+      set_envelope_direction(from.envelope_direction());
+    }
     if (from.has_envelope_step()) {
       set_envelope_step(from.envelope_step());
     }
 }
 
 bool GbSoundData_Sound1::IsInitialized() const {
-  if ((_has_bits_[0] & 0x00000fff) != 0x00000fff) return false;
+  if ((_has_bits_[0] & 0x00007fff) != 0x00007fff) return false;
   
   return true;
 }
     std::swap(act_frequency_, other->act_frequency_);
     std::swap(hi_, other->hi_);
     std::swap(duty_, other->duty_);
+    std::swap(duration_, other->duration_);
     std::swap(countdown_, other->countdown_);
+    std::swap(sweep_enabled_, other->sweep_enabled_);
     std::swap(sweep_shifts_, other->sweep_shifts_);
     std::swap(sweep_type_, other->sweep_type_);
     std::swap(sweep_step_, other->sweep_step_);
     std::swap(sweep_countdown_, other->sweep_countdown_);
     std::swap(envelope_, other->envelope_);
+    std::swap(envelope_direction_, other->envelope_direction_);
     std::swap(envelope_step_, other->envelope_step_);
     std::swap(envelope_countdown_, other->envelope_countdown_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
 
 void GbSoundData_Sound2::SharedCtor() {
   _cached_size_ = 0;
-  gb_frequency_ = 0;
+  gb_frequency_ = 0u;
   act_frequency_ = 0;
   hi_ = false;
   duty_ = 0;
 
 void GbSoundData_Sound2::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    gb_frequency_ = 0;
+    gb_frequency_ = 0u;
     act_frequency_ = 0;
     hi_ = false;
     duty_ = 0;
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
     switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // required double gb_frequency = 1;
+      // required uint32 gb_frequency = 1;
       case 1: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
                  input, &gb_frequency_)));
           set_has_gb_frequency();
         } else {
 
 void GbSoundData_Sound2::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   if (has_gb_frequency()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->gb_frequency(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->gb_frequency(), output);
   }
   
   // required double act_frequency = 2;
 
 ::google::protobuf::uint8* GbSoundData_Sound2::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   if (has_gb_frequency()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->gb_frequency(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->gb_frequency(), target);
   }
   
   // required double act_frequency = 2;
   int total_size = 0;
   
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    // required double gb_frequency = 1;
+    // required uint32 gb_frequency = 1;
     if (has_gb_frequency()) {
-      total_size += 1 + 8;
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->gb_frequency());
     }
     
     // required double act_frequency = 2;
 
 void GbSoundData_Sound3::SharedCtor() {
   _cached_size_ = 0;
-  gb_frequency_ = 0;
+  gb_frequency_ = 0u;
   act_frequency_ = 0;
   duration_ = 0;
   countdown_ = 0;
 
 void GbSoundData_Sound3::Clear() {
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    gb_frequency_ = 0;
+    gb_frequency_ = 0u;
     act_frequency_ = 0;
     duration_ = 0;
     countdown_ = 0;
   ::google::protobuf::uint32 tag;
   while ((tag = input->ReadTag()) != 0) {
     switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // required double gb_frequency = 1;
+      // required uint32 gb_frequency = 1;
       case 1: {
         if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
                  input, &gb_frequency_)));
           set_has_gb_frequency();
         } else {
 
 void GbSoundData_Sound3::SerializeWithCachedSizes(
     ::google::protobuf::io::CodedOutputStream* output) const {
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   if (has_gb_frequency()) {
-    ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->gb_frequency(), output);
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->gb_frequency(), output);
   }
   
   // required double act_frequency = 2;
 
 ::google::protobuf::uint8* GbSoundData_Sound3::SerializeWithCachedSizesToArray(
     ::google::protobuf::uint8* target) const {
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   if (has_gb_frequency()) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->gb_frequency(), target);
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->gb_frequency(), target);
   }
   
   // required double act_frequency = 2;
   int total_size = 0;
   
   if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
-    // required double gb_frequency = 1;
+    // required uint32 gb_frequency = 1;
     if (has_gb_frequency()) {
-      total_size += 1 + 8;
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->gb_frequency());
     }
     
     // required double act_frequency = 2;

gb_emulator/gb.pb.h

   
   // accessors -------------------------------------------------------
   
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   inline bool has_gb_frequency() const;
   inline void clear_gb_frequency();
   static const int kGbFrequencyFieldNumber = 1;
-  inline double gb_frequency() const;
-  inline void set_gb_frequency(double value);
+  inline ::google::protobuf::uint32 gb_frequency() const;
+  inline void set_gb_frequency(::google::protobuf::uint32 value);
   
   // required double act_frequency = 2;
   inline bool has_act_frequency() const;
   inline double duty() const;
   inline void set_duty(double value);
   
-  // required double countdown = 5;
+  // required double duration = 5;
+  inline bool has_duration() const;
+  inline void clear_duration();
+  static const int kDurationFieldNumber = 5;
+  inline double duration() const;
+  inline void set_duration(double value);
+  
+  // required double countdown = 6;
   inline bool has_countdown() const;
   inline void clear_countdown();
-  static const int kCountdownFieldNumber = 5;
+  static const int kCountdownFieldNumber = 6;
   inline double countdown() const;
   inline void set_countdown(double value);
   
-  // required uint32 sweep_shifts = 6;
+  // required bool sweep_enabled = 7;
+  inline bool has_sweep_enabled() const;
+  inline void clear_sweep_enabled();
+  static const int kSweepEnabledFieldNumber = 7;
+  inline bool sweep_enabled() const;
+  inline void set_sweep_enabled(bool value);
+  
+  // required uint32 sweep_shifts = 8;
   inline bool has_sweep_shifts() const;
   inline void clear_sweep_shifts();
-  static const int kSweepShiftsFieldNumber = 6;
+  static const int kSweepShiftsFieldNumber = 8;
   inline ::google::protobuf::uint32 sweep_shifts() const;
   inline void set_sweep_shifts(::google::protobuf::uint32 value);
   
-  // required bool sweep_type = 7;
+  // required bool sweep_type = 9;
   inline bool has_sweep_type() const;
   inline void clear_sweep_type();
-  static const int kSweepTypeFieldNumber = 7;
+  static const int kSweepTypeFieldNumber = 9;
   inline bool sweep_type() const;
   inline void set_sweep_type(bool value);
   
-  // required double sweep_step = 8;
+  // required double sweep_step = 10;
   inline bool has_sweep_step() const;
   inline void clear_sweep_step();
-  static const int kSweepStepFieldNumber = 8;
+  static const int kSweepStepFieldNumber = 10;
   inline double sweep_step() const;
   inline void set_sweep_step(double value);
   
-  // required double sweep_countdown = 9;
+  // required double sweep_countdown = 11;
   inline bool has_sweep_countdown() const;
   inline void clear_sweep_countdown();
-  static const int kSweepCountdownFieldNumber = 9;
+  static const int kSweepCountdownFieldNumber = 11;
   inline double sweep_countdown() const;
   inline void set_sweep_countdown(double value);
   
-  // required uint32 envelope = 10;
+  // required uint32 envelope = 12;
   inline bool has_envelope() const;
   inline void clear_envelope();
-  static const int kEnvelopeFieldNumber = 10;
+  static const int kEnvelopeFieldNumber = 12;
   inline ::google::protobuf::uint32 envelope() const;
   inline void set_envelope(::google::protobuf::uint32 value);
   
-  // required double envelope_step = 11;
+  // required bool envelope_direction = 13;
+  inline bool has_envelope_direction() const;
+  inline void clear_envelope_direction();
+  static const int kEnvelopeDirectionFieldNumber = 13;
+  inline bool envelope_direction() const;
+  inline void set_envelope_direction(bool value);
+  
+  // required double envelope_step = 14;
   inline bool has_envelope_step() const;
   inline void clear_envelope_step();
-  static const int kEnvelopeStepFieldNumber = 11;
+  static const int kEnvelopeStepFieldNumber = 14;
   inline double envelope_step() const;
   inline void set_envelope_step(double value);
   
-  // required double envelope_countdown = 12;
+  // required double envelope_countdown = 15;
   inline bool has_envelope_countdown() const;
   inline void clear_envelope_countdown();
-  static const int kEnvelopeCountdownFieldNumber = 12;
+  static const int kEnvelopeCountdownFieldNumber = 15;
   inline double envelope_countdown() const;
   inline void set_envelope_countdown(double value);
   
   inline void clear_has_hi();
   inline void set_has_duty();
   inline void clear_has_duty();
+  inline void set_has_duration();
+  inline void clear_has_duration();
   inline void set_has_countdown();
   inline void clear_has_countdown();
+  inline void set_has_sweep_enabled();
+  inline void clear_has_sweep_enabled();
   inline void set_has_sweep_shifts();
   inline void clear_has_sweep_shifts();
   inline void set_has_sweep_type();
   inline void clear_has_sweep_countdown();
   inline void set_has_envelope();
   inline void clear_has_envelope();
+  inline void set_has_envelope_direction();
+  inline void clear_has_envelope_direction();
   inline void set_has_envelope_step();
   inline void clear_has_envelope_step();
   inline void set_has_envelope_countdown();
   
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
   
-  double gb_frequency_;
   double act_frequency_;
   double duty_;
+  ::google::protobuf::uint32 gb_frequency_;
+  ::google::protobuf::uint32 sweep_shifts_;
+  double duration_;
   double countdown_;
   bool hi_;
+  bool sweep_enabled_;
   bool sweep_type_;
-  ::google::protobuf::uint32 sweep_shifts_;
+  bool envelope_direction_;
+  ::google::protobuf::uint32 envelope_;
   double sweep_step_;
   double sweep_countdown_;
   double envelope_step_;
   double envelope_countdown_;
-  ::google::protobuf::uint32 envelope_;
   
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(12 + 31) / 32];
+  ::google::protobuf::uint32 _has_bits_[(15 + 31) / 32];
   
   friend void  protobuf_AddDesc_gb_2eproto();
   friend void protobuf_AssignDesc_gb_2eproto();
   
   // accessors -------------------------------------------------------
   
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   inline bool has_gb_frequency() const;
   inline void clear_gb_frequency();
   static const int kGbFrequencyFieldNumber = 1;
-  inline double gb_frequency() const;
-  inline void set_gb_frequency(double value);
+  inline ::google::protobuf::uint32 gb_frequency() const;
+  inline void set_gb_frequency(::google::protobuf::uint32 value);
   
   // required double act_frequency = 2;
   inline bool has_act_frequency() const;
   
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
   
-  double gb_frequency_;
   double act_frequency_;
   double duty_;
+  ::google::protobuf::uint32 gb_frequency_;
+  bool hi_;
+  bool envelope_direction_;
   double duration_;
   double countdown_;
-  bool hi_;
-  bool envelope_direction_;
-  ::google::protobuf::uint32 envelope_;
   double envelope_step_;
   double envelope_countdown_;
+  ::google::protobuf::uint32 envelope_;
   
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32];
   
   // accessors -------------------------------------------------------
   
-  // required double gb_frequency = 1;
+  // required uint32 gb_frequency = 1;
   inline bool has_gb_frequency() const;
   inline void clear_gb_frequency();
   static const int kGbFrequencyFieldNumber = 1;
-  inline double gb_frequency() const;
-  inline void set_gb_frequency(double value);
+  inline ::google::protobuf::uint32 gb_frequency() const;
+  inline void set_gb_frequency(::google::protobuf::uint32 value);
   
   // required double act_frequency = 2;
   inline bool has_act_frequency() const;
   
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
   
-  double gb_frequency_;
   double act_frequency_;
   double duration_;
+  ::google::protobuf::uint32 gb_frequency_;
+  ::google::protobuf::uint32 wave_index_;
   double countdown_;
-  ::google::protobuf::uint32 wave_index_;
+  ::std::string* wave_pattern_;
   ::google::protobuf::uint32 out_level_;
-  ::std::string* wave_pattern_;
   
   mutable int _cached_size_;
   ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
 
 // GbSoundData_Sound1
 
-// required double gb_frequency = 1;
+// required uint32 gb_frequency = 1;
 inline bool GbSoundData_Sound1::has_gb_frequency() const {
   return (_has_bits_[0] & 0x00000001u) != 0;
 }
   _has_bits_[0] &= ~0x00000001u;
 }
 inline void GbSoundData_Sound1::clear_gb_frequency() {
-  gb_frequency_ = 0;
+  gb_frequency_ = 0u;
   clear_has_gb_frequency();
 }
-inline double GbSoundData_Sound1::gb_frequency() const {
+inline ::google::protobuf::uint32 GbSoundData_Sound1::gb_frequency() const {
   return gb_frequency_;
 }
-inline void GbSoundData_Sound1::set_gb_frequency(double value) {
+inline void GbSoundData_Sound1::set_gb_frequency(::google::protobuf::uint32 value) {
   set_has_gb_frequency();
   gb_frequency_ = value;
 }
   duty_ = value;
 }
 
-// required double countdown = 5;
+// required double duration = 5;
+inline bool GbSoundData_Sound1::has_duration() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void GbSoundData_Sound1::set_has_duration() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void GbSoundData_Sound1::clear_has_duration() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void GbSoundData_Sound1::clear_duration() {
+  duration_ = 0;
+  clear_has_duration();
+}
+inline double GbSoundData_Sound1::duration() const {
+  return duration_;
+}
+inline void GbSoundData_Sound1::set_duration(double value) {
+  set_has_duration();
+  duration_ = value;
+}
+
+// required double countdown = 6;
 inline bool GbSoundData_Sound1::has_countdown() const {
-  return (_has_bits_[0] & 0x00000010u) != 0;
+  return (_has_bits_[0] & 0x00000020u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_countdown() {
-  _has_bits_[0] |= 0x00000010u;
+  _has_bits_[0] |= 0x00000020u;
 }
 inline void GbSoundData_Sound1::clear_has_countdown() {
-  _has_bits_[0] &= ~0x00000010u;
+  _has_bits_[0] &= ~0x00000020u;
 }
 inline void GbSoundData_Sound1::clear_countdown() {
   countdown_ = 0;
   countdown_ = value;
 }
 
-// required uint32 sweep_shifts = 6;
+// required bool sweep_enabled = 7;
+inline bool GbSoundData_Sound1::has_sweep_enabled() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void GbSoundData_Sound1::set_has_sweep_enabled() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void GbSoundData_Sound1::clear_has_sweep_enabled() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void GbSoundData_Sound1::clear_sweep_enabled() {
+  sweep_enabled_ = false;
+  clear_has_sweep_enabled();
+}
+inline bool GbSoundData_Sound1::sweep_enabled() const {
+  return sweep_enabled_;
+}
+inline void GbSoundData_Sound1::set_sweep_enabled(bool value) {
+  set_has_sweep_enabled();
+  sweep_enabled_ = value;
+}
+
+// required uint32 sweep_shifts = 8;
 inline bool GbSoundData_Sound1::has_sweep_shifts() const {
-  return (_has_bits_[0] & 0x00000020u) != 0;
+  return (_has_bits_[0] & 0x00000080u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_sweep_shifts() {
-  _has_bits_[0] |= 0x00000020u;
+  _has_bits_[0] |= 0x00000080u;
 }
 inline void GbSoundData_Sound1::clear_has_sweep_shifts() {
-  _has_bits_[0] &= ~0x00000020u;
+  _has_bits_[0] &= ~0x00000080u;
 }
 inline void GbSoundData_Sound1::clear_sweep_shifts() {
   sweep_shifts_ = 0u;
   sweep_shifts_ = value;
 }
 
-// required bool sweep_type = 7;
+// required bool sweep_type = 9;
 inline bool GbSoundData_Sound1::has_sweep_type() const {
-  return (_has_bits_[0] & 0x00000040u) != 0;
+  return (_has_bits_[0] & 0x00000100u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_sweep_type() {
-  _has_bits_[0] |= 0x00000040u;
+  _has_bits_[0] |= 0x00000100u;
 }
 inline void GbSoundData_Sound1::clear_has_sweep_type() {
-  _has_bits_[0] &= ~0x00000040u;
+  _has_bits_[0] &= ~0x00000100u;
 }
 inline void GbSoundData_Sound1::clear_sweep_type() {
   sweep_type_ = false;
   sweep_type_ = value;
 }
 
-// required double sweep_step = 8;
+// required double sweep_step = 10;
 inline bool GbSoundData_Sound1::has_sweep_step() const {
-  return (_has_bits_[0] & 0x00000080u) != 0;
+  return (_has_bits_[0] & 0x00000200u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_sweep_step() {
-  _has_bits_[0] |= 0x00000080u;
+  _has_bits_[0] |= 0x00000200u;
 }
 inline void GbSoundData_Sound1::clear_has_sweep_step() {
-  _has_bits_[0] &= ~0x00000080u;
+  _has_bits_[0] &= ~0x00000200u;
 }
 inline void GbSoundData_Sound1::clear_sweep_step() {
   sweep_step_ = 0;
   sweep_step_ = value;
 }
 
-// required double sweep_countdown = 9;
+// required double sweep_countdown = 11;
 inline bool GbSoundData_Sound1::has_sweep_countdown() const {
-  return (_has_bits_[0] & 0x00000100u) != 0;
+  return (_has_bits_[0] & 0x00000400u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_sweep_countdown() {
-  _has_bits_[0] |= 0x00000100u;
+  _has_bits_[0] |= 0x00000400u;
 }
 inline void GbSoundData_Sound1::clear_has_sweep_countdown() {
-  _has_bits_[0] &= ~0x00000100u;
+  _has_bits_[0] &= ~0x00000400u;
 }
 inline void GbSoundData_Sound1::clear_sweep_countdown() {
   sweep_countdown_ = 0;
   sweep_countdown_ = value;
 }
 
-// required uint32 envelope = 10;
+// required uint32 envelope = 12;
 inline bool GbSoundData_Sound1::has_envelope() const {
-  return (_has_bits_[0] & 0x00000200u) != 0;
+  return (_has_bits_[0] & 0x00000800u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_envelope() {
-  _has_bits_[0] |= 0x00000200u;
+  _has_bits_[0] |= 0x00000800u;
 }
 inline void GbSoundData_Sound1::clear_has_envelope() {
-  _has_bits_[0] &= ~0x00000200u;
+  _has_bits_[0] &= ~0x00000800u;
 }
 inline void GbSoundData_Sound1::clear_envelope() {
   envelope_ = 0u;
   envelope_ = value;
 }
 
-// required double envelope_step = 11;
+// required bool envelope_direction = 13;
+inline bool GbSoundData_Sound1::has_envelope_direction() const {
+  return (_has_bits_[0] & 0x00001000u) != 0;
+}
+inline void GbSoundData_Sound1::set_has_envelope_direction() {
+  _has_bits_[0] |= 0x00001000u;
+}
+inline void GbSoundData_Sound1::clear_has_envelope_direction() {
+  _has_bits_[0] &= ~0x00001000u;
+}
+inline void GbSoundData_Sound1::clear_envelope_direction() {
+  envelope_direction_ = false;
+  clear_has_envelope_direction();
+}
+inline bool GbSoundData_Sound1::envelope_direction() const {
+  return envelope_direction_;
+}
+inline void GbSoundData_Sound1::set_envelope_direction(bool value) {
+  set_has_envelope_direction();
+  envelope_direction_ = value;
+}
+
+// required double envelope_step = 14;
 inline bool GbSoundData_Sound1::has_envelope_step() const {
-  return (_has_bits_[0] & 0x00000400u) != 0;
+  return (_has_bits_[0] & 0x00002000u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_envelope_step() {
-  _has_bits_[0] |= 0x00000400u;
+  _has_bits_[0] |= 0x00002000u;
 }
 inline void GbSoundData_Sound1::clear_has_envelope_step() {
-  _has_bits_[0] &= ~0x00000400u;
+  _has_bits_[0] &= ~0x00002000u;
 }
 inline void GbSoundData_Sound1::clear_envelope_step() {
   envelope_step_ = 0;
   envelope_step_ = value;
 }
 
-// required double envelope_countdown = 12;
+// required double envelope_countdown = 15;
 inline bool GbSoundData_Sound1::has_envelope_countdown() const {
-  return (_has_bits_[0] & 0x00000800u) != 0;
+  return (_has_bits_[0] & 0x00004000u) != 0;
 }
 inline void GbSoundData_Sound1::set_has_envelope_countdown() {
-  _has_bits_[0] |= 0x00000800u;
+  _has_bits_[0] |= 0x00004000u;
 }
 inline void GbSoundData_Sound1::clear_has_envelope_countdown() {
-  _has_bits_[0] &= ~0x00000800u;
+  _has_bits_[0] &= ~0x00004000u;
 }
 inline void GbSoundData_Sound1::clear_envelope_countdown() {
   envelope_countdown_ = 0;
 
 // GbSoundData_Sound2
 
-// required double gb_frequency = 1;
+// required uint32 gb_frequency = 1;
 inline bool GbSoundData_Sound2::has_gb_frequency() const {
   return (_has_bits_[0] & 0x00000001u) != 0;
 }
   _has_bits_[0] &= ~0x00000001u;
 }
 inline void GbSoundData_Sound2::clear_gb_frequency() {
-  gb_frequency_ = 0;
+  gb_frequency_ = 0u;
   clear_has_gb_frequency();
 }
-inline double GbSoundData_Sound2::gb_frequency() const {
+inline ::google::protobuf::uint32 GbSoundData_Sound2::gb_frequency() const {
   return gb_frequency_;
 }
-inline void GbSoundData_Sound2::set_gb_frequency(double value) {
+inline void GbSoundData_Sound2::set_gb_frequency(::google::protobuf::uint32 value) {
   set_has_gb_frequency();
   gb_frequency_ = value;
 }
 
 // GbSoundData_Sound3
 
-// required double gb_frequency = 1;
+// required uint32 gb_frequency = 1;
 inline bool GbSoundData_Sound3::has_gb_frequency() const {
   return (_has_bits_[0] & 0x00000001u) != 0;
 }
   _has_bits_[0] &= ~0x00000001u;
 }
 inline void GbSoundData_Sound3::clear_gb_frequency() {
-  gb_frequency_ = 0;
+  gb_frequency_ = 0u;
   clear_has_gb_frequency();
 }
-inline double GbSoundData_Sound3::gb_frequency() const {
+inline ::google::protobuf::uint32 GbSoundData_Sound3::gb_frequency() const {
   return gb_frequency_;
 }
-inline void GbSoundData_Sound3::set_gb_frequency(double value) {
+inline void GbSoundData_Sound3::set_gb_frequency(::google::protobuf::uint32 value) {
   set_has_gb_frequency();
   gb_frequency_ = value;
 }

gb_emulator/gb.proto

 {
 	message Sound1
 	{
-		required double gb_frequency        = 1;
+		required uint32 gb_frequency        = 1;
 		required double act_frequency       = 2;
 		required bool   hi                  = 3;
 		required double duty                = 4;
-		required double countdown           = 5;
-		required uint32 sweep_shifts        = 6;
-		required bool   sweep_type          = 7;
-		required double sweep_step          = 8;
-		required double sweep_countdown     = 9;
-		required uint32 envelope            = 10;
-		required double envelope_step       = 11;
-		required double envelope_countdown  = 12;
+		required double duration            = 5;
+		required double countdown           = 6;
+		required bool   sweep_enabled       = 7;
+		required uint32 sweep_shifts        = 8;
+		required bool   sweep_type          = 9;
+		required double sweep_step          = 10;
+		required double sweep_countdown     = 11;
+		required uint32 envelope            = 12;
+		required bool   envelope_direction  = 13;
+		required double envelope_step       = 14;
+		required double envelope_countdown  = 15;
 	}
 
 	message Sound2
 	{
-		required double gb_frequency        = 1;
+		required uint32 gb_frequency        = 1;
 		required double act_frequency       = 2;
 		required bool   hi                  = 3;
 		required double duty                = 4;
 
 	message Sound3
 	{
-		required double gb_frequency        = 1;
+		required uint32 gb_frequency        = 1;
 		required double act_frequency       = 2;
 		required double duration            = 3;
 		required double countdown           = 4;

gb_emulator/include/gb_emulator/gb_sound.hpp

 	// errors.
 	double excessCycles_;
 	// Current frequency in GameBoy format
-	double gbFrequency1_, gbFrequency2_, gbFrequency3_;
+	uint16_t gbFrequency1_, gbFrequency2_, gbFrequency3_;
 	// Current frequency in Hz
 	double actFrequency1_, actFrequency2_, actFrequency3_, actFrequency4_;
 	// Whether the square wave is currently in the high or low part
 	bool hi1_, hi2_;
 	// Remaining playback duration
-	double duration2_, duration3_, duration4_;
+	double duration1_, duration2_, duration3_, duration4_;
 	// Wave pattern duty
 	double duty1_, duty2_;
 	// Number of samples before toggling the high or low part of the square wave
 	double countdown1_, countdown2_, countdown3_, countdown4_;
+	// Whether the sweep shift is enabled
+	bool sweepEnabled1_;
 	// Amount the frequency is shifted by at each sweep shift
-	uint8_t sweepShifts_;
+	uint8_t sweepShifts1_;
 	// Type of shift. 0 = addition, 1 = subtraction
-	bool sweepType_;
+	bool sweepType1_;
 	// Number of samples between sweep shifts
-	double sweepStep_;
+	double sweepStep1_;
 	// Number of samples to next sweep shift
-	double sweepCountdown_;
+	double sweepCountdown1_;
 	// Current envelope state
 	uint8_t envelope1_, envelope2_, envelope4_;
 	// Direction of the envelope sweep. 0 = decrease, 1 = increase
-	bool envelopeDirection2_, envelopeDirection4_;
+	bool envelopeDirection1_, envelopeDirection2_, envelopeDirection4_;
 	// Number of samples between envelope steps
 	double envelopeStep1_, envelopeStep2_, envelopeStep4_;
 	// Number of samples to the next envelope step
 	double sound3();
 	double sound4();
 
+	// Performs the channel 1 sweep
+	bool doSweep();
+
 	// Adds the given channel amplitude to the appropriate output channels based on the value of the
 	// control bits
 	void doChannel(double amplitude, uint8_t bit, double &left, double &right);

gb_emulator/src/gb_memory.cpp

 		break;
 
 	// Sound mode 1
-	case NR10:
-		ioPorts[ptr] = val & 0x7f;
-		break;
-	case NR11:
 	case NR14:
-		ioPorts[ptr] = val & 0xc7;
+		{
+			ioPorts[ptr] = val;
+			uint16_t gbFrequency = ((val & 0x07) << 8) | ioPorts[NR13];
+			gb_.sound_.actFrequency1_ = 131072. / (0x800 - gbFrequency);
+		}
 		break;
 
 	// Sound mode 3

gb_emulator/src/gb_sound.cpp

 
 static const double PI = 3.14159265358979323846264338327950288;
 static const unsigned SOUND_BUF_SIZE = 4096;
+static const double DUTY_RATIOS[] = { 0.25, 0.5, 1, 1.5 };
 
 struct SdlAudioLock
 {
 	actFrequency4_(0),
 	hi1_(false),
 	hi2_(false),
+	duration1_(0),
 	duration2_(0),
 	duration3_(0),
 	duration4_(0),
 	countdown2_(0),
 	countdown3_(0),
 	countdown4_(0),
-	sweepShifts_(0),
-	sweepType_(0),
-	sweepStep_(0),
-	sweepCountdown_(0),
+	sweepEnabled1_(false),
+	sweepShifts1_(0),
+	sweepType1_(0),
+	sweepStep1_(0),
+	sweepCountdown1_(0),
 	envelope1_(0),
 	envelope2_(0),
 	envelope4_(0),
-	envelopeDirection2_(0),
+	envelopeDirection1_(false),
+	envelopeDirection2_(false),
 	envelopeDirection4_(false),
 	envelopeStep1_(0),
 	envelopeStep2_(0),
 
 double GbSound::sound1()
 {
+	// Return silence if nothing is playing and nothing is set to play
+	if (countdown1_ <= 0 && !(gb_.mem_.ioPorts[NR52] & 0x01) && !(gb_.mem_.ioPorts[NR14] & 0x80))
+	{
+		return 0;
+	}
+
 	if (countdown1_ <= 0)
 	{
 		// Update the sound parameters if necessary
 		if (gb_.mem_.ioPorts[NR14] & 0x80)
 		{
 			gb_.mem_.ioPorts[NR14] &= ~0x80;
+			gb_.mem_.ioPorts[NR52] |=  0x01;
 
 			// Calculate the tone frequency
 			gbFrequency1_ =
 				(gb_.mem_.ioPorts[NR13] | ((gb_.mem_.ioPorts[NR14] & 0x07) << 8));
+
+			// Set the wave pattern duty
+			duty1_ = DUTY_RATIOS[(gb_.mem_.ioPorts[NR11] & 0xc0) >> 6];
+
+			// Save the sweep parameters
+			sweepEnabled1_ = (gb_.mem_.ioPorts[NR10] & 0x70) != 0;
+			if (sweepEnabled1_)
+			{
+				sweepStep1_ = sampleRate_ / (128. / (((gb_.mem_.ioPorts[NR10] & 0x70) >> 4) + 1));
+				sweepShifts1_ = gb_.mem_.ioPorts[NR10] & 0x07;
+				sweepType1_  = (gb_.mem_.ioPorts[NR10] & 0x08) == 0x08;
+
+				// The sweep unit is always one step ahead of what is actually played, so the first
+				// note is never heard (unless the number of shifts is zero)
+				if (sweepShifts1_ && !doSweep())
+				{
+					return 0;
+				}
+				else if (!sweepShifts1_)
+				{
+					sweepCountdown1_ = sweepStep1_;
+				}
+			}
 			actFrequency1_ = 131072. / (0x800 - gbFrequency1_);
 
-			// Set the wave pattern duty
-			uint8_t duty = (gb_.mem_.ioPorts[NR11] & 0xc0) >> 6;
-			if (duty == 0x00)
+			// Save the playback duration
+			if (gb_.mem_.ioPorts[NR14] & 0x40)
 			{
-				duty1_ = 0.25;
+				duration1_ = (64 - (gb_.mem_.ioPorts[NR11] & 0x3f)) * (1. / 256) * sampleRate_;
 			}
-			else if (duty == 0x01)
+			else
 			{
-				duty1_ = 0.5;
-			}
-			else if (duty == 0x02)
-			{
-				duty1_ = 1;
-			}
-			else if (duty == 0x03)
-			{
-				duty1_ = 1.5;
-			}
-
-			// Save the sweep parameters
-			sweepStep_ = ((gb_.mem_.ioPorts[NR10] & 0x70) >> 4) / 128. * sampleRate_;
-			if (sweepStep_)
-			{
-				sweepShifts_ = gb_.mem_.ioPorts[NR10] & 0x07;
-				sweepType_   = (gb_.mem_.ioPorts[NR10] & 0x08) != 0;
-				sweepCountdown_ = sweepStep_;
+				duration1_ = numeric_limits<double>::infinity();
 			}
 
 			// Set the envelope parameters
-			envelope1_ = (gb_.mem_.ioPorts[NR12] & 0xf0) >> 4;
-			if (envelope1_)
-			{
-				envelopeStep1_ = ((gb_.mem_.ioPorts[NR12] & 0x07) * (1. / 64)) * sampleRate_;
-				envelopeCountdown1_ = envelopeStep1_;
-
-				if ((gb_.mem_.ioPorts[NR12] & 0x0f) == 0x0f)
-				{
-					clog << "envelope up\n";
-				}
-			}
+			envelope1_ = gb_.mem_.ioPorts[NR12] >> 4;
+			envelopeDirection1_ = (gb_.mem_.ioPorts[NR12] & 0x08) == 0x08;
+			envelopeStep1_ = ((gb_.mem_.ioPorts[NR12] & 0x07) * (1. / 64)) * sampleRate_;
+			envelopeCountdown1_ = envelopeStep1_;
 		}
-		else if (!actFrequency1_)
+		else
 		{
-			return 0;
+			// Adjust the envelope amplitude
+			adjustEnvelope(envelope1_, envelopeDirection1_, envelopeStep1_, envelopeCountdown1_);
 		}
 
-		// Toggle hi/lo wave and reset the countdown if there is any sound to play
+		// Toggle hi/lo wave
 		hi1_ = !hi1_;
-		countdown1_ += 1 / actFrequency1_ / 2 * (hi1_ ? duty1_ : 2 - duty1_) * sampleRate_;
 
-		// Adjust the envelope amplitude
-		if (envelope1_ && envelopeStep1_)
+		double duration = 1 / actFrequency1_ / 2 * (hi1_ ? duty1_ : 2 - duty1_) * sampleRate_;
+		countdown1_ += duration;
+		duration1_  -= duration;
+
+		// Reset the playback bit if the duration has elapsed
+		if (duration1_ <= 0)
 		{
-			while (envelope1_ && envelopeCountdown1_ <= 0)
-			{
-				--envelope1_;
-				envelopeCountdown1_ += envelopeStep1_;
-			}
+			gb_.mem_.ioPorts[NR52] &= ~0x01;
+		}
+
+		// Depending on the parameters the duration might be shorter than a single sample, so just
+		// toggle the hi/lo flag repeatedly to catch up
+		while (countdown1_ < 0)
+		{
+			hi1_ = !hi1_;
+			countdown1_ += duration;
+			duration1_  -= duration;
 		}
 	}
 
-	double amplitude = 0x200;
-	amplitude = amplitude * (envelope1_ / 15.);
+	double amplitude = 0x200 * (envelope1_ / 15.);
 
 	// Handle the frequency sweep
-	if (sweepStep_ && --sweepCountdown_ <= 0)
+	if (sweepEnabled1_ && --sweepCountdown1_ <= 0)
 	{
-		double difference = gbFrequency1_ / pow(2., sweepShifts_);
-		if (sweepType_)
-			difference = -difference;
-		double newGbFrequency = gbFrequency1_ + difference;
-		if (newGbFrequency <= 0)
+		// If the number of shifts is set to zero we just stop after a single iteration
+		if (!sweepShifts1_)
 		{
-			sweepStep_ = 0;
+			gb_.mem_.ioPorts[NR52] &= ~0x01;
 		}
 		else
 		{
-			gbFrequency1_ = newGbFrequency;
-			actFrequency1_ = 131072. / (0x800 - gbFrequency1_);
-			sweepCountdown_ += sweepStep_;
+			doSweep();
 		}
 	}
 
 	// Handle the envelope step
-	if (envelope1_ && envelopeStep1_)
+	if (envelopeStep1_ &&
+		(envelope1_ > 0  && !envelopeDirection1_) ||
+		(envelope1_ < 15 &&  envelopeDirection1_))
 	{
 		--envelopeCountdown1_;
 	}
 			actFrequency2_ = 131072. / (0x800 - gbFrequency2_);
 
 			// Set the wave pattern duty
-			uint8_t duty = gb_.mem_.ioPorts[NR21] >> 6;
-			static const double duties[] = { 0.25, 0.5, 1, 1.5 };
-			duty2_ = duties[duty];
+			duty2_ = DUTY_RATIOS[gb_.mem_.ioPorts[NR21] >> 6];
 
 			// Save the playback duration
 			if (gb_.mem_.ioPorts[NR24] & 0x40)
 	return amplitude;
 }
 
+bool GbSound::doSweep()
+{
+	int16_t difference = gbFrequency1_ >> sweepShifts1_;
+	if (sweepType1_)
+	{
+		difference = -difference;
+	}
+	uint16_t newGbFrequency = gbFrequency1_ + difference;
+	// Check for overflow
+	if (newGbFrequency & 0xf800)
+	{
+		gb_.mem_.ioPorts[NR52] &= ~0x01;
+		return false;
+	}
+	else
+	{
+		gbFrequency1_ = newGbFrequency;
+		actFrequency1_ = 131072. / (0x800 - gbFrequency1_);
+		sweepCountdown1_ += sweepStep1_;
+			
+		gb_.mem_.ioPorts[NR13]  = static_cast<uint8_t>(gbFrequency1_);
+		gb_.mem_.ioPorts[NR14] &= ~0x07;
+		gb_.mem_.ioPorts[NR14] |= static_cast<uint8_t>(gbFrequency1_ >> 8);
+
+		return true;
+	}
+}
+
 void GbSound::adjustEnvelope(uint8_t &envelope, bool envelopeDirection, double envelopeStep,
 	double &envelopeCountdown)
 {
 	excessCycles_ = data.excess_cycles();
 
 	const GbSoundData::Sound1 &sound1 = data.sound_1();
-	gbFrequency1_ = sound1.gb_frequency();
+	gbFrequency1_ = static_cast<uint16_t>(sound1.gb_frequency());
 	actFrequency1_ = sound1.act_frequency();
 	hi1_ = sound1.hi();
 	duty1_ = sound1.duty();
+	duration1_ = sound1.duration();
 	countdown1_ = sound1.countdown();
-	sweepShifts_ = static_cast<uint8_t>(sound1.sweep_shifts());
-	sweepType_ = sound1.sweep_type();
-	sweepStep_ = sound1.sweep_step();
-	sweepCountdown_ = sound1.sweep_countdown();
+	sweepEnabled1_ = sound1.sweep_enabled();
+	sweepShifts1_ = static_cast<uint8_t>(sound1.sweep_shifts());
+	sweepType1_ = sound1.sweep_type();
+	sweepStep1_ = sound1.sweep_step();
+	sweepCountdown1_ = sound1.sweep_countdown();
 	envelope1_ = static_cast<uint8_t>(sound1.envelope());
+	envelopeDirection1_ = sound1.envelope_direction();
 	envelopeStep1_ = sound1.envelope_step();
 	envelopeCountdown1_ = sound1.envelope_countdown();
 
 	const GbSoundData::Sound2 &sound2 = data.sound_2();
-	gbFrequency2_ = sound2.gb_frequency();
+	gbFrequency2_ = static_cast<uint16_t>(sound2.gb_frequency());
 	actFrequency2_ = sound2.act_frequency();
 	hi2_ = sound2.hi();
 	duty2_ = sound2.duty();
 	envelopeCountdown2_ = sound2.envelope_countdown();
 
 	const GbSoundData::Sound3 &sound3 = data.sound_3();
-	gbFrequency3_ = sound3.gb_frequency();
+	gbFrequency3_ = static_cast<uint16_t>(sound3.gb_frequency());
 	actFrequency3_ = sound3.act_frequency();
 	duration3_ = sound3.duration();
 	countdown3_ = sound3.countdown();
 	sound1.set_act_frequency(actFrequency1_);
 	sound1.set_hi(hi1_);
 	sound1.set_duty(duty1_);
+	sound1.set_duration(duration1_);
 	sound1.set_countdown(countdown1_);
-	sound1.set_sweep_shifts(sweepShifts_);
-	sound1.set_sweep_type(sweepType_);
-	sound1.set_sweep_step(sweepStep_);
-	sound1.set_sweep_countdown(sweepCountdown_);
+	sound1.set_sweep_enabled(sweepEnabled1_);
+	sound1.set_sweep_shifts(sweepShifts1_);
+	sound1.set_sweep_type(sweepType1_);
+	sound1.set_sweep_step(sweepStep1_);
+	sound1.set_sweep_countdown(sweepCountdown1_);
 	sound1.set_envelope(envelope1_);
+	sound1.set_envelope_direction(envelopeDirection1_);
 	sound1.set_envelope_step(envelopeStep1_);
 	sound1.set_envelope_countdown(envelopeCountdown1_);