/sfxr/Synth.hx

http://github.com/tong/sfxr · Haxe · 398 lines · 348 code · 40 blank · 10 comment · 71 complexity · b539da14d1509f814b205cdbb1574460 MD5 · raw file

  1. package sfxr;
  2. import flash.events.SampleDataEvent;
  3. import flash.media.Sound;
  4. import flash.media.SoundChannel;
  5. import flash.utils.ByteArray;
  6. import flash.utils.Endian;
  7. class Synth {
  8. /**
  9. square: 0
  10. saw: 1
  11. sin: 2
  12. noise: 3
  13. */
  14. public var waveType : Int;
  15. /** Samples per second - only used for .wav export */
  16. public var sampleRate : UInt;
  17. /** Bits per sample - only used for .wav export */
  18. public var bitDepth : UInt;
  19. /** Overall volume of the sound (0 to 1) */
  20. public var masterVolume : Float;
  21. public var attackTime : Float;
  22. public var sustainTime : Float;
  23. public var sustainPunch : Float;
  24. public var decayTime : Float;
  25. public var startFrequency : Float;
  26. public var minFrequency : Float;
  27. public var slide : Float;
  28. public var deltaSlide : Float;
  29. public var vibratoDepth : Float;
  30. public var vibratoSpeed : Float;
  31. public var changeAmount : Float;
  32. public var changeSpeed : Float;
  33. public var squareDuty : Float;
  34. public var dutySweep : Float;
  35. public var repeatSpeed : Float;
  36. public var phaserOffset : Float;
  37. public var phaserSweep : Float;
  38. public var lpFilterCutoff : Float;
  39. public var lpFilterCutoffSweep : Float;
  40. public var lpFilterResonance : Float;
  41. public var hpFilterCutoff : Float;
  42. public var hpFilterCutoffSweep : Float;
  43. var _envelopeVolume : Float;
  44. var _envelopeStage : Int;
  45. var _envelopeTime : Float;
  46. var _envelopeLength : Float;
  47. var _envelopeLength0 : Float;
  48. var _envelopeLength1 : Float;
  49. var _envelopeLength2 : Float;
  50. var _envelopeOverLength0 : Float;
  51. var _envelopeOverLength1 : Float;
  52. var _envelopeOverLength2 : Float;
  53. var _envelopeFullLength : Float;
  54. var _phase : Float;
  55. var _pos : Float;
  56. var _period : Float;
  57. var _periodTemp : Float;
  58. var _maxPeriod : Float;
  59. var _slide : Float;
  60. var _deltaSlide : Float;
  61. var _vibratoPhase : Float;
  62. var _vibratoSpeed : Float;
  63. var _vibratoAmplitude : Float;
  64. var _changeAmount : Float;
  65. var _changeTime : Float;
  66. var _changeLimit : Float;
  67. var _squareDuty : Float;
  68. var _dutySweep : Float;
  69. var _repeatTime : Float;
  70. var _repeatLimit : Float;
  71. var _phaserOffset : Float;
  72. var _phaserDeltaOffset : Float;
  73. var _phaserInt : Int;
  74. var _phaserPos : Int;
  75. var _phaserBuffer : flash.Vector<Float>;
  76. var _lpFilterPos : Float;
  77. var _lpFilterOldPos : Float;
  78. var _lpFilterDeltaPos : Float;
  79. var _lpFilterCutoff : Float;
  80. var _lpFilterDeltaCutoff : Float;
  81. var _lpFilterDamping : Float;
  82. var _hpFilterPos : Float;
  83. var _hpFilterCutoff : Float;
  84. var _hpFilterDeltaCutoff : Float;
  85. var _noiseBuffer : flash.Vector<Float>;
  86. var _superSample : Float;
  87. var _sample : Float;
  88. var _sampleCount : UInt;
  89. var _bufferSample : Float;
  90. var sound : Sound;
  91. var channel : SoundChannel;
  92. public function new( ?waveType : Int,
  93. sampleRate : UInt = 44100, bitDepth : UInt = 16,
  94. masterVolume : Float = 0.5 ) {
  95. this.waveType = ( waveType != null ) ? waveType : 0;
  96. this.sampleRate = sampleRate;
  97. this.bitDepth = bitDepth;
  98. this.masterVolume = masterVolume;
  99. attackTime = sustainTime = sustainPunch = decayTime = 0;
  100. startFrequency = minFrequency =
  101. slide = deltaSlide =
  102. vibratoDepth = vibratoSpeed =
  103. changeAmount = changeSpeed =
  104. squareDuty = dutySweep =
  105. repeatSpeed =
  106. phaserOffset = phaserSweep =
  107. lpFilterCutoff = lpFilterCutoffSweep = lpFilterResonance =
  108. hpFilterCutoff = hpFilterCutoffSweep = 0.0;
  109. }
  110. public function play() {
  111. stop();
  112. reset( true );
  113. if( sound == null ) {
  114. sound = new Sound();
  115. sound.addEventListener( SampleDataEvent.SAMPLE_DATA, onSampleData );
  116. }
  117. channel = sound.play();
  118. }
  119. public function stop() {
  120. if( channel != null ) {
  121. channel.stop();
  122. channel = null;
  123. }
  124. }
  125. public function validate() {
  126. if( sampleRate != 22050 ) sampleRate = 44100;
  127. if( bitDepth != 8 ) bitDepth = 16;
  128. masterVolume = clamp1(masterVolume);
  129. attackTime = clamp1(attackTime);
  130. sustainTime = clamp1(sustainTime);
  131. sustainPunch = clamp1(sustainPunch);
  132. decayTime = clamp1(decayTime);
  133. startFrequency = clamp1(startFrequency);
  134. minFrequency = clamp1(minFrequency);
  135. slide = clamp2(slide);
  136. deltaSlide = clamp2(deltaSlide);
  137. vibratoDepth = clamp1(vibratoDepth);
  138. vibratoSpeed = clamp1(vibratoSpeed);
  139. changeAmount = clamp2(changeAmount);
  140. changeSpeed = clamp1(changeSpeed);
  141. squareDuty = clamp1(squareDuty);
  142. dutySweep = clamp2(dutySweep);
  143. repeatSpeed = clamp1(repeatSpeed);
  144. phaserOffset = clamp2(phaserOffset);
  145. phaserSweep = clamp2(phaserSweep);
  146. lpFilterCutoff = clamp1(lpFilterCutoff);
  147. lpFilterCutoffSweep = clamp2(lpFilterCutoffSweep);
  148. lpFilterResonance = clamp1(lpFilterResonance);
  149. hpFilterCutoff = clamp1(hpFilterCutoff);
  150. hpFilterCutoffSweep = clamp2(hpFilterCutoffSweep);
  151. }
  152. public function clone() : Synth {
  153. var out = new Synth();
  154. out.copyFrom( this, false );
  155. return out;
  156. }
  157. public function copyFrom( synth : Synth, shouldDeleteCache : Bool = true) {
  158. // if( shouldDeleteCache ) deleteCache();
  159. waveType = synth.waveType;
  160. attackTime = synth.attackTime;
  161. sustainTime = synth.sustainTime;
  162. sustainPunch = synth.sustainPunch;
  163. decayTime = synth.decayTime;
  164. startFrequency = synth.startFrequency;
  165. minFrequency = synth.minFrequency;
  166. slide = synth.slide;
  167. deltaSlide = synth.deltaSlide;
  168. vibratoDepth = synth.vibratoDepth;
  169. vibratoSpeed = synth.vibratoSpeed;
  170. changeAmount = synth.changeAmount;
  171. changeSpeed = synth.changeSpeed;
  172. squareDuty = synth.squareDuty;
  173. dutySweep = synth.dutySweep;
  174. repeatSpeed = synth.repeatSpeed;
  175. phaserOffset = synth.phaserOffset;
  176. phaserSweep = synth.phaserSweep;
  177. lpFilterCutoff = synth.lpFilterCutoff;
  178. lpFilterCutoffSweep = synth.lpFilterCutoffSweep;
  179. lpFilterResonance = synth.lpFilterResonance;
  180. hpFilterCutoff = synth.hpFilterCutoff;
  181. hpFilterCutoffSweep = synth.hpFilterCutoffSweep;
  182. masterVolume = synth.masterVolume;
  183. validate();
  184. }
  185. function onSampleData( e : SampleDataEvent ) {
  186. synthWave( e.data, 3072, true );
  187. }
  188. function synthWave( buffer : ByteArray, length : Int, waveData : Bool = false ) {
  189. var finished = false;
  190. _sampleCount = 0;
  191. _bufferSample = 0.0;
  192. for( i in 0...length ) {
  193. if( finished )
  194. return;
  195. if( _repeatLimit != 0 ) {
  196. if( ++_repeatTime >= _repeatLimit ) {
  197. _repeatTime = 0;
  198. reset( false );
  199. }
  200. }
  201. if( _changeLimit != 0 ) {
  202. if( ++_changeTime >= _changeLimit ) {
  203. _changeLimit = 0;
  204. _period *= _changeAmount;
  205. }
  206. }
  207. _slide += _deltaSlide;
  208. _period = _period * _slide;
  209. if( _period > _maxPeriod ) {
  210. _period = _maxPeriod;
  211. if( minFrequency > 0.0 ) finished = true;
  212. }
  213. _periodTemp = _period;
  214. if( _vibratoAmplitude > 0.0 ) {
  215. _vibratoPhase += _vibratoSpeed;
  216. _periodTemp = _period * ( 1.0 + Math.sin(_vibratoPhase) * _vibratoAmplitude );
  217. }
  218. _periodTemp = Std.int( _periodTemp );
  219. if( _periodTemp < 8 ) _periodTemp = 8;
  220. _squareDuty += _dutySweep;
  221. if( _squareDuty < 0.0 ) _squareDuty = 0.0;
  222. else if( _squareDuty > 0.5 ) _squareDuty = 0.5;
  223. if( ++_envelopeTime > _envelopeLength ) {
  224. _envelopeTime = 0;
  225. switch( ++_envelopeStage ) {
  226. case 1 : _envelopeLength = _envelopeLength1;
  227. case 2 : _envelopeLength = _envelopeLength2;
  228. }
  229. }
  230. switch( _envelopeStage ) {
  231. case 0 : _envelopeVolume = _envelopeTime * _envelopeOverLength0;
  232. case 1 : _envelopeVolume = 1.0 + (1.0 - _envelopeTime * _envelopeOverLength1) * 2.0 * sustainPunch;
  233. case 2 : _envelopeVolume = 1.0 - _envelopeTime * _envelopeOverLength2;
  234. case 3 : _envelopeVolume = 0.0; finished = true;
  235. }
  236. _phaserOffset += _phaserDeltaOffset;
  237. _phaserInt = Std.int( _phaserOffset );
  238. if( _phaserInt < 0 ) _phaserInt = -_phaserInt;
  239. else if( _phaserInt > 1023 ) _phaserInt = 1023;
  240. if( _hpFilterDeltaCutoff != 0.0 ) {
  241. _hpFilterCutoff *- _hpFilterDeltaCutoff;
  242. if( _hpFilterCutoff < 0.00001 ) _hpFilterCutoff = 0.00001;
  243. else if( _hpFilterCutoff > 0.1 ) _hpFilterCutoff = 0.1;
  244. }
  245. _superSample = 0.0;
  246. for( j in 0...8 ) {
  247. _sample = 0.0;
  248. _phase++;
  249. if( _phase >= _periodTemp ) {
  250. _phase = _phase % _periodTemp;
  251. if( waveType == 3 ) {
  252. for( n in 0...32 ) {
  253. _noiseBuffer[n] = Math.random() * 2.0 - 1.0;
  254. }
  255. }
  256. }
  257. _pos = _phase / _periodTemp;
  258. switch( waveType ) {
  259. case 0 : _sample = (_pos < _squareDuty) ? 0.5 : -0.5;
  260. case 1 : _sample = 1.0 - _pos * 2.0;
  261. case 2 : _sample = Math.sin(_pos * Math.PI * 2.0);
  262. case 3 : _sample = _noiseBuffer[Std.int(_phase * 32 / Std.int(_periodTemp))];
  263. }
  264. _lpFilterOldPos = _lpFilterPos;
  265. _lpFilterCutoff *= _lpFilterDeltaCutoff;
  266. if( _lpFilterCutoff < 0.0 ) _lpFilterCutoff = 0.0;
  267. else if( _lpFilterCutoff > 0.1 ) _lpFilterCutoff = 0.1;
  268. if( lpFilterCutoff != 1.0 ) {
  269. _lpFilterDeltaPos += (_sample - _lpFilterPos) * _lpFilterCutoff * 4;
  270. _lpFilterDeltaPos -= _lpFilterDeltaPos * _lpFilterDamping;
  271. } else {
  272. _lpFilterPos = _sample;
  273. _lpFilterDeltaPos = 0.0;
  274. }
  275. _lpFilterPos += _lpFilterDeltaPos;
  276. _hpFilterPos += _lpFilterPos - _lpFilterOldPos;
  277. _hpFilterPos -= _hpFilterPos * _lpFilterCutoff;
  278. _sample = _hpFilterPos;
  279. _phaserBuffer[_phaserPos&1023] = _sample;
  280. _sample += _phaserBuffer[(_phaserPos - _phaserInt + 1024) & 1023];
  281. _phaserPos = (_phaserPos + 1) & 1023;
  282. _superSample += _sample;
  283. }
  284. _superSample = masterVolume * masterVolume * _envelopeVolume * _superSample / 8.0;
  285. if( _superSample > 1.0 ) _superSample = 1.0;
  286. if( _superSample < -1.0 ) _superSample = -1.0;
  287. if( waveData ) {
  288. buffer.writeFloat(_superSample);
  289. buffer.writeFloat(_superSample);
  290. } else {
  291. _bufferSample += _superSample;
  292. _sampleCount++;
  293. if( sampleRate == 44100 || _sampleCount == 2 ) {
  294. _bufferSample /= _sampleCount;
  295. _sampleCount = 0;
  296. if( bitDepth == 16 ) buffer.writeShort(Std.int(32000.0 * _bufferSample));
  297. else buffer.writeByte( Std.int( _bufferSample * 127 + 128 ) );
  298. _bufferSample = 0.0;
  299. }
  300. }
  301. }
  302. }
  303. function reset( total : Bool ) {
  304. _period = 100.0 / ( startFrequency * startFrequency + 0.001 );
  305. _maxPeriod = 100.0 / ( minFrequency * minFrequency + 0.001 );
  306. _slide = 1.0 - slide * slide * slide * 0.01;
  307. _deltaSlide = -deltaSlide * deltaSlide * deltaSlide * 0.000001;
  308. _squareDuty = 0.5 - squareDuty * 0.5;
  309. _dutySweep = -dutySweep * 0.00005;
  310. if( changeAmount > 0.0 ) _changeAmount = 1.0 - changeAmount*changeAmount * 0.9;
  311. else _changeAmount = 1.0 + changeAmount * changeAmount * 10.0;
  312. _changeTime = 0;
  313. _changeLimit = ( changeSpeed == 1.0 ) ? 0 : (1.0 - changeSpeed) * (1.0 - changeSpeed) * 20000 + 32;
  314. if( total ) {
  315. _phase = 0;
  316. _lpFilterPos = _lpFilterDeltaPos = 0.0;
  317. _lpFilterCutoff = lpFilterCutoff * lpFilterCutoff * lpFilterCutoff * 0.1;
  318. _lpFilterDeltaCutoff = 1.0 + lpFilterCutoffSweep * 0.0001;
  319. _lpFilterDamping = 5.0 / (1.0 + lpFilterResonance * lpFilterResonance * 20.0) * (0.01 + _lpFilterCutoff);
  320. if( _lpFilterDamping > 0.8 ) _lpFilterDamping = 0.8;
  321. _hpFilterPos = 0.0;
  322. _hpFilterCutoff = hpFilterCutoff * hpFilterCutoff * 0.1;
  323. _hpFilterDeltaCutoff = 1.0 + hpFilterCutoffSweep * 0.0003;
  324. _vibratoPhase = 0.0;
  325. _vibratoSpeed = vibratoSpeed * vibratoSpeed * 0.01;
  326. _vibratoAmplitude = vibratoDepth * 0.5;
  327. _envelopeVolume = 0.0;
  328. _envelopeStage = 0;
  329. _envelopeTime = 0;
  330. _envelopeLength0 = attackTime * attackTime * 100000.0;
  331. _envelopeLength1 = sustainTime * sustainTime * 100000.0;
  332. _envelopeLength2 = decayTime * decayTime * 100000.0;
  333. _envelopeLength = _envelopeLength0;
  334. _envelopeFullLength = _envelopeLength0 + _envelopeLength1 + _envelopeLength2;
  335. _envelopeOverLength0 = 1.0 / _envelopeLength0;
  336. _envelopeOverLength1 = 1.0 / _envelopeLength1;
  337. _envelopeOverLength2 = 1.0 / _envelopeLength2;
  338. _phaserOffset = phaserOffset * phaserOffset * 1020.0;
  339. if( phaserOffset < 0.0 ) _phaserOffset = -_phaserOffset;
  340. _phaserDeltaOffset = phaserSweep * phaserSweep;
  341. if( _phaserDeltaOffset < 0.0 ) _phaserDeltaOffset = -_phaserDeltaOffset;
  342. _phaserPos = 0;
  343. if( _phaserBuffer == null ) _phaserBuffer = new flash.Vector<Float>( 1024, true );
  344. if( _noiseBuffer == null ) _noiseBuffer = new flash.Vector<Float>( 32, true );
  345. for( i in 0...1024 ) _phaserBuffer[i] = 0.0;
  346. for( i in 0...32 ) _noiseBuffer[i] = Math.random() * 2.0 - 1.0;
  347. _repeatTime = 0;
  348. if( repeatSpeed == 0.0 ) _repeatLimit = 0;
  349. else _repeatLimit = Std.int((1.0-repeatSpeed) * (1.0-repeatSpeed) * 20000) + 32;
  350. }
  351. }
  352. inline function clamp1( v : Float ) : Float {
  353. return (v > 1.0) ? 1.0 : ((v < 0.0) ? 0.0 : v);
  354. }
  355. inline function clamp2( v : Float ) : Float {
  356. return (v > 1.0) ? 1.0 : ((v < -1.0) ? -1.0 : v);
  357. }
  358. }