voice.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // ---------------------------------------------------------------------------
  2. // This file is part of reSID, a MOS6581 SID emulator engine.
  3. // Copyright (C) 2004 Dag Lem <resid@nimrod.no>
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. // ---------------------------------------------------------------------------
  19. #define __VOICE_CC__
  20. #include "voice.h"
  21. // ----------------------------------------------------------------------------
  22. // Constructor.
  23. // ----------------------------------------------------------------------------
  24. Voice::Voice()
  25. {
  26. set_chip_model(MOS6581);
  27. }
  28. // ----------------------------------------------------------------------------
  29. // Set chip model.
  30. // ----------------------------------------------------------------------------
  31. void Voice::set_chip_model(chip_model model)
  32. {
  33. wave.set_chip_model(model);
  34. if (model == MOS6581) {
  35. // The waveform D/A converter introduces a DC offset in the signal
  36. // to the envelope multiplying D/A converter. The "zero" level of
  37. // the waveform D/A converter can be found as follows:
  38. //
  39. // Measure the "zero" voltage of voice 3 on the SID audio output
  40. // pin, routing only voice 3 to the mixer ($d417 = $0b, $d418 =
  41. // $0f, all other registers zeroed).
  42. //
  43. // Then set the sustain level for voice 3 to maximum and search for
  44. // the waveform output value yielding the same voltage as found
  45. // above. This is done by trying out different waveform output
  46. // values until the correct value is found, e.g. with the following
  47. // program:
  48. //
  49. // lda #$08
  50. // sta $d412
  51. // lda #$0b
  52. // sta $d417
  53. // lda #$0f
  54. // sta $d418
  55. // lda #$f0
  56. // sta $d414
  57. // lda #$21
  58. // sta $d412
  59. // lda #$01
  60. // sta $d40e
  61. //
  62. // ldx #$00
  63. // lda #$38 ; Tweak this to find the "zero" level
  64. //l cmp $d41b
  65. // bne l
  66. // stx $d40e ; Stop frequency counter - freeze waveform output
  67. // brk
  68. //
  69. // The waveform output range is 0x000 to 0xfff, so the "zero"
  70. // level should ideally have been 0x800. In the measured chip, the
  71. // waveform output "zero" level was found to be 0x380 (i.e. $d41b
  72. // = 0x38) at 5.94V.
  73. wave_zero = 0x380;
  74. // The envelope multiplying D/A converter introduces another DC
  75. // offset. This is isolated by the following measurements:
  76. //
  77. // * The "zero" output level of the mixer at full volume is 5.44V.
  78. // * Routing one voice to the mixer at full volume yields
  79. // 6.75V at maximum voice output (wave = 0xfff, sustain = 0xf)
  80. // 5.94V at "zero" voice output (wave = any, sustain = 0x0)
  81. // 5.70V at minimum voice output (wave = 0x000, sustain = 0xf)
  82. // * The DC offset of one voice is (5.94V - 5.44V) = 0.50V
  83. // * The dynamic range of one voice is |6.75V - 5.70V| = 1.05V
  84. // * The DC offset is thus 0.50V/1.05V ~ 1/2 of the dynamic range.
  85. //
  86. // Note that by removing the DC offset, we get the following ranges for
  87. // one voice:
  88. // y > 0: (6.75V - 5.44V) - 0.50V = 0.81V
  89. // y < 0: (5.70V - 5.44V) - 0.50V = -0.24V
  90. // The scaling of the voice amplitude is not symmetric about y = 0;
  91. // this follows from the DC level in the waveform output.
  92. voice_DC = 0x800*0xff;
  93. }
  94. else {
  95. // No DC offsets in the MOS8580.
  96. wave_zero = 0x800;
  97. voice_DC = 0;
  98. }
  99. }
  100. // ----------------------------------------------------------------------------
  101. // Set sync source.
  102. // ----------------------------------------------------------------------------
  103. void Voice::set_sync_source(Voice* source)
  104. {
  105. wave.set_sync_source(&source->wave);
  106. }
  107. // ----------------------------------------------------------------------------
  108. // Register functions.
  109. // ----------------------------------------------------------------------------
  110. void Voice::writeCONTROL_REG(reg8 control)
  111. {
  112. wave.writeCONTROL_REG(control);
  113. envelope.writeCONTROL_REG(control);
  114. }
  115. // ----------------------------------------------------------------------------
  116. // SID reset.
  117. // ----------------------------------------------------------------------------
  118. void Voice::reset()
  119. {
  120. wave.reset();
  121. envelope.reset();
  122. }