2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  ESFMu :  emulator  for  the  ESS  " ESFM "  enhanced  OPL3  clone 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Copyright  ( C )  2023  Kagamiin ~ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  file  includes  code  and  data  from  the  Nuked  OPL3  project ,  copyright  ( C ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  2013 - 2023  Nuke . YKT .  Its  usage ,  modification  and  redistribution  is  allowed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  under  the  terms  of  the  GNU  Lesser  General  Public  License  version  2.1  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  later . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  ESFMu  is  free  software :  you  can  redistribute  it  and / or  modify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  it  under  the  terms  of  the  GNU  Lesser  General  Public  License  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  published  by  the  Free  Software  Foundation ,  either  version  2.1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  of  the  License ,  or  ( at  your  option )  any  later  version . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  ESFMu  is  distributed  in  the  hope  that  it  will  be  useful , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  but  WITHOUT  ANY  WARRANTY ;  without  even  the  implied  warranty  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE .   See  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  GNU  Lesser  General  Public  License  for  more  details . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  You  should  have  received  a  copy  of  the  GNU  Lesser  General  Public  License 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  along  with  ESFMu .  If  not ,  see  < https : //www.gnu.org/licenses/>.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  ESFMu  wouldn ' t  have  been  possible  without  the  hard  work  and  dedication  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  retro  computer  hardware  research  and  preservation  community . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  I ' d  like  to  thank : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   -  Nuke . YKT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         Developer  of  Nuked  OPL3 ,  which  was  the  basis  for  ESFMu ' s  code  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         also  a  great  learning  resource  on  Yamaha  FM  synthesis  for  myself . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         Nuke . YKT  also  gives  shoutouts  on  behalf  of  Nuked  OPL3  to : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         -  MAME  Development  Team ( Jarek  Burczynski ,  Tatsuyuki  Satoh ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *               Feedback  and  Rhythm  part  calculation  information . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         -  forums . submarine . org . uk ( carbon14 ,  opl3 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *               Tremolo  and  phase  generator  calculation  information . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         -  OPLx  decapsulated ( Matthew  Gambrell ,  Olli  Niemitalo ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *               OPL2  ROMs . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         -  siliconpr0n . org ( John  McMaster ,  digshadow ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *               YMF262  and  VRC  VII  decaps  and  die  shots . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  -  rainwarrior 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        For  performing  the  initial  research  on  ESFM  drivers  and  documenting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        ESS ' s  patent  on  native  mode  operator  organization . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  -  jwt27 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        For  kickstarting  the  ESFM  research  project  and  compiling  rainwarrior ' s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        findings  and  more  in  an  accessible  document  ( " ESFM Demystified " ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  -  pachuco / CatButts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        For  documenting  ESS ' s  patent  on  ESFM ' s  feedback  implementation ,  which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *        was  vital  in  getting  ESFMu ' s  sound  output  to  be  accurate . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  -  And  everybody  who  helped  out  with  real  hardware  testing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "esfm.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdint.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdlib.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stddef.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <string.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <stdbool.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Log - scale  quarter  sine  table  extracted  from  OPL3  ROM ;  taken  straight  from 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Nuked  OPL3  source  code . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  TODO :  Extract  sine  table  from  ESFM  die  scans . . .  does  ESFM  even  use  a  sine 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  table ?  Patent  documents  give  a  hint  to  a  possible  method  of  generating  sine 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  waves  using  some  sort  of  boolean  logic  wizardry  ( lol ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  uint16_t  logsinrom [ 256 ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x859 ,  0x6c3 ,  0x607 ,  0x58b ,  0x52e ,  0x4e4 ,  0x4a6 ,  0x471 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x443 ,  0x41a ,  0x3f5 ,  0x3d3 ,  0x3b5 ,  0x398 ,  0x37e ,  0x365 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x34e ,  0x339 ,  0x324 ,  0x311 ,  0x2ff ,  0x2ed ,  0x2dc ,  0x2cd , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x2bd ,  0x2af ,  0x2a0 ,  0x293 ,  0x286 ,  0x279 ,  0x26d ,  0x261 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x256 ,  0x24b ,  0x240 ,  0x236 ,  0x22c ,  0x222 ,  0x218 ,  0x20f , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x206 ,  0x1fd ,  0x1f5 ,  0x1ec ,  0x1e4 ,  0x1dc ,  0x1d4 ,  0x1cd , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x1c5 ,  0x1be ,  0x1b7 ,  0x1b0 ,  0x1a9 ,  0x1a2 ,  0x19b ,  0x195 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x18f ,  0x188 ,  0x182 ,  0x17c ,  0x177 ,  0x171 ,  0x16b ,  0x166 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x160 ,  0x15b ,  0x155 ,  0x150 ,  0x14b ,  0x146 ,  0x141 ,  0x13c , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x137 ,  0x133 ,  0x12e ,  0x129 ,  0x125 ,  0x121 ,  0x11c ,  0x118 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x114 ,  0x10f ,  0x10b ,  0x107 ,  0x103 ,  0x0ff ,  0x0fb ,  0x0f8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x0f4 ,  0x0f0 ,  0x0ec ,  0x0e9 ,  0x0e5 ,  0x0e2 ,  0x0de ,  0x0db , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x0d7 ,  0x0d4 ,  0x0d1 ,  0x0cd ,  0x0ca ,  0x0c7 ,  0x0c4 ,  0x0c1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x0be ,  0x0bb ,  0x0b8 ,  0x0b5 ,  0x0b2 ,  0x0af ,  0x0ac ,  0x0a9 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x0a7 ,  0x0a4 ,  0x0a1 ,  0x09f ,  0x09c ,  0x099 ,  0x097 ,  0x094 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x092 ,  0x08f ,  0x08d ,  0x08a ,  0x088 ,  0x086 ,  0x083 ,  0x081 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x07f ,  0x07d ,  0x07a ,  0x078 ,  0x076 ,  0x074 ,  0x072 ,  0x070 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x06e ,  0x06c ,  0x06a ,  0x068 ,  0x066 ,  0x064 ,  0x062 ,  0x060 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x05e ,  0x05c ,  0x05b ,  0x059 ,  0x057 ,  0x055 ,  0x053 ,  0x052 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x050 ,  0x04e ,  0x04d ,  0x04b ,  0x04a ,  0x048 ,  0x046 ,  0x045 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x043 ,  0x042 ,  0x040 ,  0x03f ,  0x03e ,  0x03c ,  0x03b ,  0x039 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x038 ,  0x037 ,  0x035 ,  0x034 ,  0x033 ,  0x031 ,  0x030 ,  0x02f , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x02e ,  0x02d ,  0x02b ,  0x02a ,  0x029 ,  0x028 ,  0x027 ,  0x026 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x025 ,  0x024 ,  0x023 ,  0x022 ,  0x021 ,  0x020 ,  0x01f ,  0x01e , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x01d ,  0x01c ,  0x01b ,  0x01a ,  0x019 ,  0x018 ,  0x017 ,  0x017 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x016 ,  0x015 ,  0x014 ,  0x014 ,  0x013 ,  0x012 ,  0x011 ,  0x011 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x010 ,  0x00f ,  0x00f ,  0x00e ,  0x00d ,  0x00d ,  0x00c ,  0x00c , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x00b ,  0x00a ,  0x00a ,  0x009 ,  0x009 ,  0x008 ,  0x008 ,  0x007 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x007 ,  0x007 ,  0x006 ,  0x006 ,  0x005 ,  0x005 ,  0x005 ,  0x004 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x004 ,  0x004 ,  0x003 ,  0x003 ,  0x003 ,  0x002 ,  0x002 ,  0x002 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x002 ,  0x001 ,  0x001 ,  0x001 ,  0x001 ,  0x001 ,  0x001 ,  0x001 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x000 ,  0x000 ,  0x000 ,  0x000 ,  0x000 ,  0x000 ,  0x000 ,  0x000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Inverse  exponent  table  extracted  from  OPL3  ROM ;  taken  straight  from 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Nuked  OPL3  source  code . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  TODO :  Verify  if  ESFM  uses  an  exponent  table  or  if  it  possibly  uses  another 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  method  to  skirt  around  Yamaha ' s  patents ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  uint16_t  exprom [ 256 ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x7fa ,  0x7f5 ,  0x7ef ,  0x7ea ,  0x7e4 ,  0x7df ,  0x7da ,  0x7d4 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x7cf ,  0x7c9 ,  0x7c4 ,  0x7bf ,  0x7b9 ,  0x7b4 ,  0x7ae ,  0x7a9 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x7a4 ,  0x79f ,  0x799 ,  0x794 ,  0x78f ,  0x78a ,  0x784 ,  0x77f , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x77a ,  0x775 ,  0x770 ,  0x76a ,  0x765 ,  0x760 ,  0x75b ,  0x756 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x751 ,  0x74c ,  0x747 ,  0x742 ,  0x73d ,  0x738 ,  0x733 ,  0x72e , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x729 ,  0x724 ,  0x71f ,  0x71a ,  0x715 ,  0x710 ,  0x70b ,  0x706 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x702 ,  0x6fd ,  0x6f8 ,  0x6f3 ,  0x6ee ,  0x6e9 ,  0x6e5 ,  0x6e0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x6db ,  0x6d6 ,  0x6d2 ,  0x6cd ,  0x6c8 ,  0x6c4 ,  0x6bf ,  0x6ba , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x6b5 ,  0x6b1 ,  0x6ac ,  0x6a8 ,  0x6a3 ,  0x69e ,  0x69a ,  0x695 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x691 ,  0x68c ,  0x688 ,  0x683 ,  0x67f ,  0x67a ,  0x676 ,  0x671 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x66d ,  0x668 ,  0x664 ,  0x65f ,  0x65b ,  0x657 ,  0x652 ,  0x64e , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x649 ,  0x645 ,  0x641 ,  0x63c ,  0x638 ,  0x634 ,  0x630 ,  0x62b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x627 ,  0x623 ,  0x61e ,  0x61a ,  0x616 ,  0x612 ,  0x60e ,  0x609 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x605 ,  0x601 ,  0x5fd ,  0x5f9 ,  0x5f5 ,  0x5f0 ,  0x5ec ,  0x5e8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x5e4 ,  0x5e0 ,  0x5dc ,  0x5d8 ,  0x5d4 ,  0x5d0 ,  0x5cc ,  0x5c8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x5c4 ,  0x5c0 ,  0x5bc ,  0x5b8 ,  0x5b4 ,  0x5b0 ,  0x5ac ,  0x5a8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x5a4 ,  0x5a0 ,  0x59c ,  0x599 ,  0x595 ,  0x591 ,  0x58d ,  0x589 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x585 ,  0x581 ,  0x57e ,  0x57a ,  0x576 ,  0x572 ,  0x56f ,  0x56b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x567 ,  0x563 ,  0x560 ,  0x55c ,  0x558 ,  0x554 ,  0x551 ,  0x54d , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x549 ,  0x546 ,  0x542 ,  0x53e ,  0x53b ,  0x537 ,  0x534 ,  0x530 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x52c ,  0x529 ,  0x525 ,  0x522 ,  0x51e ,  0x51b ,  0x517 ,  0x514 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x510 ,  0x50c ,  0x509 ,  0x506 ,  0x502 ,  0x4ff ,  0x4fb ,  0x4f8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x4f4 ,  0x4f1 ,  0x4ed ,  0x4ea ,  0x4e7 ,  0x4e3 ,  0x4e0 ,  0x4dc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x4d9 ,  0x4d6 ,  0x4d2 ,  0x4cf ,  0x4cc ,  0x4c8 ,  0x4c5 ,  0x4c2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x4be ,  0x4bb ,  0x4b8 ,  0x4b5 ,  0x4b1 ,  0x4ae ,  0x4ab ,  0x4a8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x4a4 ,  0x4a1 ,  0x49e ,  0x49b ,  0x498 ,  0x494 ,  0x491 ,  0x48e , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x48b ,  0x488 ,  0x485 ,  0x482 ,  0x47e ,  0x47b ,  0x478 ,  0x475 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x472 ,  0x46f ,  0x46c ,  0x469 ,  0x466 ,  0x463 ,  0x460 ,  0x45d , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x45a ,  0x457 ,  0x454 ,  0x451 ,  0x44e ,  0x44b ,  0x448 ,  0x445 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x442 ,  0x43f ,  0x43c ,  0x439 ,  0x436 ,  0x433 ,  0x430 ,  0x42d , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x42a ,  0x428 ,  0x425 ,  0x422 ,  0x41f ,  0x41c ,  0x419 ,  0x416 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									0x414 ,  0x411 ,  0x40e ,  0x40b ,  0x408 ,  0x406 ,  0x403 ,  0x400 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Frequency  multiplier  table  multiplied  by  2 ;  taken  straight  from  Nuked  OPL3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  source  code . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  uint8_t  mt [ 16 ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									1 ,  2 ,  4 ,  6 ,  8 ,  10 ,  12 ,  14 ,  16 ,  18 ,  20 ,  20 ,  24 ,  24 ,  30 ,  30 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  is  used  during  the  envelope  generation  to  apply  KSL  to  the  envelope  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  determining  how  much  to  shift  right  the  keyscale  attenuation  value  before 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  adding  it  to  the  envelope  level . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  uint8_t  kslshift [ 4 ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									8 ,  1 ,  2 ,  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  encodes  which  emulation  mode  channels  are  the  secondary  channel  in  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  4 - op  channel  pair  ( where  the  entry  is  non - negative ) ,  and  which  is  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  corresponding  primary  channel  for  that  secondary  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  int  emu_4op_secondary_to_primary [ 18 ]  =  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									- 1 ,  - 1 ,  - 1 ,  0 ,   1 ,   2 ,  - 1 ,  - 1 ,  - 1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									- 1 ,  - 1 ,  - 1 ,  9 ,  10 ,  11 ,  - 1 ,  - 1 ,  - 1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Envelope  generator  dither  table ,  taken  straight  from  Nuked  OPL3  source  code . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  uint8_t  eg_incstep [ 4 ] [ 4 ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  0 ,  0 ,  0 ,  0  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  1 ,  0 ,  0 ,  0  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  1 ,  0 ,  1 ,  0  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  1 ,  1 ,  1 ,  0  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  int13 ( * envelope_sinfunc ) ( uint10  phase ,  uint10  envelope ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  uint12  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_exp ( uint16  level )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( level  >  0x1fff ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										level  =  0x1fff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ( exprom [ level  &  0xff ]  < <  1 )  > >  ( level  > >  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin0 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint16  out  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int13  neg  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x200 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										neg  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x100 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ ( phase  &  0xff )  ^  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ phase  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( out  +  ( envelope  < <  3 ) )  *  neg ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin1 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint16  out  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x200 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  0x1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( phase  &  0x100 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ ( phase  &  0xff )  ^  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ phase  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( out  +  ( envelope  < <  3 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin2 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint16  out  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x100 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ ( phase  &  0xff )  ^  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ phase  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( out  +  ( envelope  < <  3 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin3 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint16  out  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x100 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  0x1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ phase  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( out  +  ( envelope  < <  3 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin4 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint16  out  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int13  neg  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( phase  &  0x300 )  = =  0x100 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										neg  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x200 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  0x1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( phase  &  0x80 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ ( ( phase  ^  0xff )  < <  1 )  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ ( phase  < <  1 )  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( out  +  ( envelope  < <  3 ) )  *  neg ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin5 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint16  out  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x200 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  0x1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( phase  &  0x80 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ ( ( phase  ^  0xff )  < <  1 )  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										out  =  logsinrom [ ( phase  < <  1 )  &  0xff ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( out  +  ( envelope  < <  3 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin6 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int13  neg  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x200 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										neg  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( envelope  < <  3 )  *  neg ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int13  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc_sin7 ( uint10  phase ,  uint10  envelope )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint16  out  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int13  neg  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									phase  & =  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( phase  &  0x200 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										neg  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										phase  =  ( phase  &  0x1ff )  ^  0x1ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									out  =  phase  < <  3 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 16:28:50 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ESFM_envelope_calc_exp ( out  +  ( envelope  < <  3 ) )  *  neg ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  envelope_sinfunc  envelope_sin [ 8 ]  =  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin3 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin4 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin5 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin6 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_envelope_calc_sin7 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_envelope_calc ( esfm_slot  * slot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint8  nonzero ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint8  rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint5  rate_hi ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint2  rate_lo ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint4  reg_rate  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint4  ks ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint8  eg_shift ,  shift ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  eg_off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint9  eg_rout ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int16  eg_inc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  reset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  key_on ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bool  key_on_signal ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									key_on  =  * slot - > in . key_on ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! slot - > chip - > native_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  pair_primary_idx  =  emu_4op_secondary_to_primary [ slot - > channel - > channel_idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( pair_primary_idx  > =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											esfm_channel  * pair_primary  =  & slot - > channel - > chip - > channels [ pair_primary_idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( pair_primary - > emu_mode_4op_enable ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												key_on  =  * pair_primary - > slots [ 0 ] . in . key_on ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else  if  ( ( slot - > channel - > channel_idx  = =  7  | |  slot - > channel - > channel_idx  = =  8 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  slot - > slot_idx  = =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											key_on  =  slot - > channel - > key_on_2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . eg_output  =  slot - > in . eg_position  +  ( slot - > t_level  < <  2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										+  ( slot - > in . eg_ksl_offset  > >  kslshift [ slot - > ksl ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > tremolo_en ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uint8  tremolo ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( slot - > chip - > native_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tremolo  =  slot - > channel - > chip - > tremolo  > >  ( ( ! slot - > tremolo_deep  < <  1 )  +  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tremolo  =  slot - > channel - > chip - > tremolo  > >  ( ( ! slot - > chip - > emu_tremolo_deep  < <  1 )  +  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_output  + =  tremolo ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > in . eg_delay_run  & &  slot - > in . eg_delay_counter  <  32768 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_counter + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// triggers on key-on edge
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( key_on  & &  ! slot - > in . key_on_gate ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_run  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_counter  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-17 08:33:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										slot - > in . eg_delay_transitioned_01  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_transitioned_01_gate  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_transitioned_10  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_transitioned_10_gate  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_counter_compare  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( slot - > env_delay  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slot - > in . eg_delay_counter_compare  =  256  < <  slot - > env_delay ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( ! key_on ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_delay_run  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2024-01-17 08:33:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// TODO: is this really how the chip behaves? Can it only transition the envelope delay once? Am I implementing this in a sane way? I feel like this is a roundabout hack.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( slot - > in . eg_delay_transitioned_10  & &  ! slot - > in . eg_delay_transitioned_10_gate )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										( slot - > in . eg_delay_transitioned_01  & &  ! slot - > in . eg_delay_transitioned_01_gate ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-17 08:33:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										slot - > in . eg_delay_counter_compare  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( slot - > env_delay  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slot - > in . eg_delay_counter_compare  =  256  < <  slot - > env_delay ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( slot - > in . eg_delay_transitioned_10 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slot - > in . eg_delay_transitioned_10_gate  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( slot - > in . eg_delay_transitioned_01 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slot - > in . eg_delay_transitioned_01_gate  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2024-01-17 08:33:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( key_on  & &  ( ( slot - > in . eg_delay_counter  > =  slot - > in . eg_delay_counter_compare )  | |  ! slot - > chip - > native_mode ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										key_on_signal  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										key_on_signal  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( key_on  & &  slot - > in . eg_state  = =  EG_RELEASE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-17 08:33:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ( slot - > in . eg_delay_counter  > =  slot - > in . eg_delay_counter_compare )  | |  ! slot - > chip - > native_mode ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reset  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reg_rate  =  slot - > attack_rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reg_rate  =  slot - > release_rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( slot - > in . eg_state ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  EG_ATTACK : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reg_rate  =  slot - > attack_rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  EG_DECAY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reg_rate  =  slot - > decay_rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  EG_SUSTAIN : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! slot - > env_sustaining ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													reg_rate  =  slot - > release_rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  EG_RELEASE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reg_rate  =  slot - > release_rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									slot - > in . key_on_gate  =  key_on ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									slot - > in . phase_reset  =  reset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ks  =  slot - > in . keyscale  > >  ( ( ! slot - > ksr )  < <  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									nonzero  =  ( reg_rate  ! =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rate  =  ks  +  ( reg_rate  < <  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rate_hi  =  rate  > >  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rate_lo  =  rate  &  0x03 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( rate_hi  &  0x10 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rate_hi  =  0x0f ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									eg_shift  =  rate_hi  +  slot - > chip - > eg_clocks ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									shift  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( nonzero ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( rate_hi  <  12 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( slot - > chip - > eg_tick ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												switch  ( eg_shift ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													case  12 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														shift  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													case  13 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														shift  =  ( rate_lo  > >  1 )  &  0x01 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													case  14 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														shift  =  rate_lo  &  0x01 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											shift  =  ( rate_hi  &  0x03 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												+  eg_incstep [ rate_lo ] [ slot - > chip - > global_timer  &  0x03 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( shift  &  0x04 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												shift  =  0x03 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! shift ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												shift  =  slot - > chip - > eg_tick ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									eg_rout  =  slot - > in . eg_position ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									eg_inc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									eg_off  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Instant attack */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( reset  & &  rate_hi  = =  0x0f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										eg_rout  =  0x00 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Envelope off */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( slot - > in . eg_position  &  0x1f8 )  = =  0x1f8 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										eg_off  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > in . eg_state  ! =  EG_ATTACK  & &  ! reset  & &  eg_off ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										eg_rout  =  0x1ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( slot - > in . eg_state ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  EG_ATTACK : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( slot - > in . eg_position  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slot - > in . eg_state  =  EG_DECAY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											else  if  ( key_on_signal  & &  shift  >  0  & &  rate_hi  ! =  0x0f ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												eg_inc  =  ~ slot - > in . eg_position  > >  ( 4  -  shift ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  EG_DECAY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ( slot - > in . eg_position  > >  4 )  = =  slot - > sustain_lvl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slot - > in . eg_state  =  EG_SUSTAIN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											else  if  ( ! eg_off  & &  ! reset  & &  shift  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												eg_inc  =  1  < <  ( shift  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  EG_SUSTAIN : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  EG_RELEASE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! eg_off  & &  ! reset  & &  shift  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												eg_inc  =  1  < <  ( shift  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . eg_position  =  ( eg_rout  +  eg_inc )  &  0x1ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Key off */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( reset ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_state  =  EG_ATTACK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-18 16:01:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! key_on_signal ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . eg_state  =  EG_RELEASE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_phase_generate ( esfm_slot  * slot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									esfm_chip  * chip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint10  f_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32  basefreq ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  rm_xor ,  n_bit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint23  noise ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint10  phase ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip  =  slot - > chip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									f_num  =  slot - > f_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > vibrato_en ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int8_t  range ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uint8_t  vibpos ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										range  =  ( f_num  > >  7 )  &  7 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										vibpos  =  chip - > vibrato_pos ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ( vibpos  &  3 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											range  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else  if  ( vibpos  &  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											range  > > =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										range  > > =  ! slot - > vibrato_deep ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( vibpos  &  4 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											range  =  - range ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f_num  + =  range ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									basefreq  =  ( f_num  < <  slot - > block )  > >  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									phase  =  ( uint10 ) ( slot - > in . phase_acc  > >  9 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > in . phase_reset ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . phase_acc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . phase_acc  + =  ( basefreq  *  mt [ slot - > mult ] )  > >  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . phase_acc  & =  ( 1  < <  19 )  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . phase_out  =  phase ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Noise mode (rhythm) sounds */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									noise  =  chip - > lfsr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > slot_idx  = =  3  & &  slot - > rhy_noise ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										esfm_slot  * prev_slot  =  & slot - > channel - > slots [ 2 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit2  =  ( phase  > >  2 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit3  =  ( phase  > >  3 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit7  =  ( phase  > >  7 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit8  =  ( phase  > >  8 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_tc_bit3  =  ( prev_slot - > in . phase_out  > >  3 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_tc_bit5  =  ( prev_slot - > in . phase_out  > >  5 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rm_xor  =  ( chip - > rm_hh_bit2  ^  chip - > rm_hh_bit7 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       |  ( chip - > rm_hh_bit3  ^  chip - > rm_tc_bit5 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       |  ( chip - > rm_tc_bit3  ^  chip - > rm_tc_bit5 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch ( slot - > rhy_noise ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// SD
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slot - > in . phase_out  =  ( chip - > rm_hh_bit8  < <  9 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													|  ( ( chip - > rm_hh_bit8  ^  ( noise  &  1 ) )  < <  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// HH
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slot - > in . phase_out  =  rm_xor  < <  9 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( rm_xor  ^  ( noise  &  1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slot - > in . phase_out  | =  0xd0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slot - > in . phase_out  | =  0x34 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  3 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// TC
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slot - > in . phase_out  =  ( rm_xor  < <  9 )  |  0x80 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n_bit  =  ( ( noise  > >  14 )  ^  noise )  &  0x01 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip - > lfsr  =  ( noise  > >  1 )  |  ( n_bit  < <  22 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_phase_generate_emu ( esfm_slot  * slot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									esfm_chip  * chip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint3  block ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint10  f_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32  basefreq ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  rm_xor ,  n_bit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint23  noise ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint10  phase ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  pair_primary_idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip  =  slot - > chip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									block  =  slot - > channel - > slots [ 0 ] . block ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									f_num  =  slot - > channel - > slots [ 0 ] . f_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pair_primary_idx  =  emu_4op_secondary_to_primary [ slot - > channel - > channel_idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( pair_primary_idx  > =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										esfm_channel  * pair_primary  =  & slot - > channel - > chip - > channels [ pair_primary_idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( pair_primary - > emu_mode_4op_enable ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											block  =  pair_primary - > slots [ 0 ] . block ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f_num  =  pair_primary - > slots [ 0 ] . f_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > vibrato_en ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int8_t  range ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uint8_t  vibpos ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										range  =  ( f_num  > >  7 )  &  7 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										vibpos  =  chip - > vibrato_pos ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ( vibpos  &  3 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											range  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else  if  ( vibpos  &  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											range  > > =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										range  > > =  ! chip - > emu_vibrato_deep ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( vibpos  &  4 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											range  =  - range ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f_num  + =  range ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									basefreq  =  ( f_num  < <  block )  > >  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									phase  =  ( uint10 ) ( slot - > in . phase_acc  > >  9 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > in . phase_reset ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > in . phase_acc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . phase_acc  + =  ( basefreq  *  mt [ slot - > mult ] )  > >  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . phase_acc  & =  ( 1  < <  19 )  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . phase_out  =  phase ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Noise mode (rhythm) sounds */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									noise  =  chip - > lfsr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// HH
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > channel - > channel_idx  = =  7  & &  slot - > slot_idx  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit2  =  ( phase  > >  2 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit3  =  ( phase  > >  3 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit7  =  ( phase  > >  7 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_hh_bit8  =  ( phase  > >  8 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// TC
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > channel - > channel_idx  = =  8  & &  slot - > slot_idx  = =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_tc_bit3  =  ( phase  > >  3 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > rm_tc_bit5  =  ( phase  > >  5 )  &  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( chip - > emu_rhy_mode_flags  &  0x20 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rm_xor  =  ( chip - > rm_hh_bit2  ^  chip - > rm_hh_bit7 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       |  ( chip - > rm_hh_bit3  ^  chip - > rm_tc_bit5 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       |  ( chip - > rm_tc_bit3  ^  chip - > rm_tc_bit5 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( slot - > channel - > channel_idx  = =  7 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( slot - > slot_idx  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// HH
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slot - > in . phase_out  =  rm_xor  < <  9 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( rm_xor  ^  ( noise  &  1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slot - > in . phase_out  | =  0xd0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													slot - > in . phase_out  | =  0x34 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											else  if  ( slot - > slot_idx  = =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// SD
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												slot - > in . phase_out  =  ( chip - > rm_hh_bit8  < <  9 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													|  ( ( chip - > rm_hh_bit8  ^  ( noise  &  1 ) )  < <  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else  if  ( slot - > channel - > channel_idx  = =  8  & &  slot - > slot_idx  = =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// TC
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slot - > in . phase_out  =  ( rm_xor  < <  9 )  |  0x80 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n_bit  =  ( ( noise  > >  14 )  ^  noise )  &  0x01 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip - > lfsr  =  ( noise  > >  1 )  |  ( n_bit  < <  22 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 15:49:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/**
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  TODO :  Figure  out  what ' s  ACTUALLY  going  on  inside  the  real  chip ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  is  not  accurate  at  all ,  but  it ' s  the  closest  I  was  able  to  get  with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  empirical  testing  ( and  it ' s  closer  than  nothing ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int16  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_slot3_noise3_mod_input_calc ( esfm_slot  * slot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									esfm_channel  * channel  =  slot - > channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									envelope_sinfunc  wavegen  =  envelope_sin [ channel - > slots [ 2 ] . waveform ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int16  phase ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int13  output_buf  =  * channel - > slots [ 1 ] . in . mod_input ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Go through previous slots' partial results and recalculate outputs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// (we skip slot 0 because its calculation happens at the end, not at the beginning)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  1 ;  i  <  3 ;  i + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// double the pitch
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										phase  =  channel - > slots [ i ] . in . phase_acc  > >  8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( channel - > slots [ i ] . mod_in_level ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											phase  + =  output_buf  > >  ( 7  -  channel - > slots [ i ] . mod_in_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										output_buf  =  wavegen ( ( uint10 ) ( phase  &  0x3ff ) ,  channel - > slots [ i ] . in . eg_output ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  output_buf  > >  ( 8  -  slot - > mod_in_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_slot_generate ( esfm_slot  * slot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									envelope_sinfunc  wavegen  =  envelope_sin [ slot - > waveform ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int16  phase  =  slot - > in . phase_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > mod_in_level ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-22 15:49:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( slot - > slot_idx  = =  3  & &  slot - > rhy_noise  = =  3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											phase  + =  ESFM_slot3_noise3_mod_input_calc ( slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											phase  + =  * slot - > in . mod_input  > >  ( 7  -  slot - > mod_in_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 07:10:37 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . output  =  wavegen ( ( uint10 ) ( phase  &  0x3ff ) ,  slot - > in . eg_output ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > output_level ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int13  output_value  =  slot - > in . output  > >  ( 7  -  slot - > output_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > channel - > output [ 0 ]  + =  output_value  &  slot - > out_enable [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > channel - > output [ 1 ]  + =  output_value  &  slot - > out_enable [ 1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_slot_generate_emu ( esfm_slot  * slot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									esfm_chip  * chip  =  slot - > chip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									envelope_sinfunc  wavegen  =  envelope_sin [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > waveform  &  ( chip - > emu_newmode  ! =  0  ?  0x07  :  0x03 ) ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  rhythm_slot_double_volume  =  ( slot - > chip - > emu_rhy_mode_flags  &  0x20 )  ! =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  slot - > channel - > channel_idx  > =  6  & &  slot - > channel - > channel_idx  <  9 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int16  phase  =  slot - > in . phase_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int14  output_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									phase  + =  * slot - > in . mod_input  &  slot - > in . emu_mod_enable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slot - > in . output  =  wavegen ( ( uint10 ) ( phase  &  0x3ff ) ,  slot - > in . eg_output ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									output_value  =  ( slot - > in . output  &  slot - > in . emu_output_enable )  < <  rhythm_slot_double_volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( chip - > emu_newmode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > channel - > output [ 0 ]  + =  output_value  &  slot - > channel - > slots [ 0 ] . out_enable [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > channel - > output [ 1 ]  + =  output_value  &  slot - > channel - > slots [ 0 ] . out_enable [ 1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > channel - > output [ 0 ]  + =  output_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slot - > channel - > output [ 1 ]  + =  output_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_slot_calc_feedback ( esfm_slot  * slot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									esfm_chip  * chip  =  slot - > chip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32  basefreq ,  phase_offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint3  block ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint10  f_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int13  in1  =  0 ,  in2  =  0 ,  wave_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int16  phase ,  phase_feedback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint19  regressed_phase ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  iter_counter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									envelope_sinfunc  wavegen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( slot - > mod_in_level ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chip - > native_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											wavegen  =  envelope_sin [ slot - > waveform ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											wavegen  =  envelope_sin [ slot - > waveform  &  ( 0x03  |  ( 0x02  < <  ( chip - > emu_newmode  ! =  0 ) ) ) ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f_num  =  slot - > f_num ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										block  =  slot - > block ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										basefreq  =  ( f_num  < <  block )  > >  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										phase_offset  =  ( basefreq  *  mt [ slot - > mult ] )  > >  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( iter_counter  =  28 ;  iter_counter  > =  0 ;  iter_counter - - ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											regressed_phase  =  ( uint19 ) ( ( uint32 ) slot - > in . phase_acc  -  iter_counter  *  phase_offset )  &  ( ( 1  < <  19 )  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											phase  =  ( int16 ) ( regressed_phase  > >  9 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											phase_feedback  =  ( in1  +  in2 )  > >  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											phase  + =  phase_feedback  > >  ( 7  -  slot - > mod_in_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											wave_out  =  wavegen ( ( uint10 ) ( phase  &  0x3ff ) ,  slot - > in . eg_output ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											in2  =  in1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											in1  =  wave_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// TODO: Figure out - is this how the ESFM chip does it, like the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// patent literally says? (it's really hacky...)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										//   slot->in.output = wave_out;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// This would be the more canonical way to do it, reusing the rest of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// the synthesis pipeline to finish the calculation:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chip - > native_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slot - > in . feedback_buf  =  phase_feedback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											slot - > in . feedback_buf  =  phase_feedback  > >  ( 7  -  slot - > mod_in_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_process_channel ( esfm_channel  * channel )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  slot_idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									channel - > output [ 0 ]  =  channel - > output [ 1 ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( slot_idx  =  0 ;  slot_idx  <  4 ;  slot_idx + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										esfm_slot  * slot  =  & channel - > slots [ slot_idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ESFM_envelope_calc ( slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ESFM_phase_generate ( slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( slot_idx  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ESFM_slot_generate ( slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ESFM feedback calculation takes a large number of clock cycles, so
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// defer slot 0 generation to the end
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// TODO: verify this behavior on real hardware
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_slot_calc_feedback ( & channel - > slots [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_slot_generate ( & channel - > slots [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_process_channel_emu ( esfm_channel  * channel )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  slot_idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									channel - > output [ 0 ]  =  channel - > output [ 1 ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( slot_idx  =  0 ;  slot_idx  <  2 ;  slot_idx + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										esfm_slot  * slot  =  & channel - > slots [ slot_idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ESFM_envelope_calc ( slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ESFM_phase_generate_emu ( slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( slot_idx  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ESFM_slot_generate_emu ( slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ESFM feedback calculation takes a large number of clock cycles, so
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// defer slot 0 generation to the end
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// TODO: verify this behavior on real hardware
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( channel - > slots [ 0 ] . in . mod_input  = =  & channel - > slots [ 0 ] . in . feedback_buf ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ESFM_slot_calc_feedback ( & channel - > slots [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_slot_generate_emu ( & channel - > slots [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int16_t  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_clip_sample ( int32  sample )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// TODO: Supposedly, the real ESFM chip actually overflows rather than
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// clipping. Verify that.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( sample  >  32767 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sample  =  32767 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( sample  <  - 32768 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sample  =  - 32768 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ( int16_t ) sample ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_update_timers ( esfm_chip  * chip )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Tremolo
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( chip - > global_timer  &  0x3f )  = =  0x3f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > tremolo_pos  =  ( chip - > tremolo_pos  +  1 )  %  210 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chip - > tremolo_pos  <  105 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											chip - > tremolo  =  chip - > tremolo_pos ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											chip - > tremolo  =  ( 210  -  chip - > tremolo_pos ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Vibrato
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( chip - > global_timer  &  0x3ff )  = =  0x3ff ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > vibrato_pos  =  ( chip - > vibrato_pos  +  1 )  &  0x07 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip - > global_timer  =  ( chip - > global_timer  +  1 )  &  0x3ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Envelope generator dither clocks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip - > eg_clocks  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( chip - > eg_timer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uint8  shift  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( shift  <  36  & &  ( ( chip - > eg_timer  > >  shift )  &  1 )  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											shift + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( shift  < =  12 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											chip - > eg_clocks  =  shift  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( chip - > eg_tick  | |  chip - > eg_timer_overflow ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chip - > eg_timer  = =  ( 1llu  < <  36 )  -  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											chip - > eg_timer  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											chip - > eg_timer_overflow  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											chip - > eg_timer + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											chip - > eg_timer_overflow  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip - > eg_tick  ^ =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define KEY_ON_REGS_START (18 * 4 * 8) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_reg_write_chan_idx ( esfm_chip  * chip ,  uint16_t  reg )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  which_reg  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( chip - > native_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bool  is_key_on_reg  =  reg  > =  KEY_ON_REGS_START  & &  reg  <  ( KEY_ON_REGS_START  +  20 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( is_key_on_reg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											which_reg  =  reg  -  KEY_ON_REGS_START ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uint8_t  reg_low  =  reg  &  0xff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bool  high  =  reg  &  0x100 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bool  is_key_on_reg  =  reg_low  > =  0xb0  & &  reg_low  <  0xb9 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( is_key_on_reg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											which_reg  =  ( reg_low  &  0x0f )  +  high  *  9 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  which_reg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_update_write_buffer ( esfm_chip  * chip )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									esfm_write_buf  * write_buf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  note_off_written [ 20 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  bassdrum_written  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  20 ;  i + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										note_off_written [ i ]  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while ( ( write_buf  =  & chip - > write_buf [ chip - > write_buf_start ] ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										write_buf - > valid  & &  write_buf - > timestamp  < =  chip - > write_buf_timestamp ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  is_which_note_on_reg  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ESFM_reg_write_chan_idx ( chip ,  write_buf - > address ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( is_which_note_on_reg  > =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ( chip - > native_mode  & &  ( write_buf - > data  &  0x01 )  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												| |  ( ! chip - > native_mode  & &  ( write_buf - > data  &  0x20 )  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// this is a note off command; note down that we got note off for this channel
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												note_off_written [ is_which_note_on_reg ]  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// this is a note on command; have we gotten a note off for this channel in this cycle?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( note_off_written [ is_which_note_on_reg ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													// we have a conflict; let the note off be processed first and defer the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													// rest of the buffer to the next cycle
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( chip - > native_mode  & &  write_buf - > address  = =  0x4bd ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											| |  ( ! chip - > native_mode  & &  ( write_buf - > address  &  0xff )  = =  0xbd ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// bassdrum register write (rhythm mode note-on/off control)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// have we already written to the bassdrum register in this cycle
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bassdrum_written )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// we have a conflict
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bassdrum_written  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										write_buf - > valid  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ESFM_write_reg ( chip ,  write_buf - > address ,  write_buf - > data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > write_buf_start  =  ( chip - > write_buf_start  +  1 )  %  ESFM_WRITEBUF_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip - > write_buf_timestamp + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_generate ( esfm_chip  * chip ,  int16_t  * buf )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  channel_idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chip - > output_accm [ 0 ]  =  chip - > output_accm [ 1 ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( channel_idx  =  0 ;  channel_idx  <  18 ;  channel_idx + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										esfm_channel  * channel  =  & chip - > channels [ channel_idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chip - > native_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ESFM_process_channel ( channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ESFM_process_channel_emu ( channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > output_accm [ 0 ]  + =  channel - > output [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chip - > output_accm [ 1 ]  + =  channel - > output [ 1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									buf [ 0 ]  =  ESFM_clip_sample ( chip - > output_accm [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									buf [ 1 ]  =  ESFM_clip_sample ( chip - > output_accm [ 1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_update_timers ( chip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ESFM_update_write_buffer ( chip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int16_t  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_get_channel_output_native ( esfm_chip  * chip ,  int  channel_idx )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int16_t  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int32_t  temp_mix  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( channel_idx  <  0  | |  channel_idx  > =  18 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  4 ;  i + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										esfm_slot  * slot  =  & chip - > channels [ channel_idx ] . slots [ i ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( slot - > output_level ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int13  output_value  =  slot - > in . output  > >  ( 7  -  slot - > output_level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											temp_mix  + =  output_value  &  slot - > out_enable [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											temp_mix  + =  output_value  &  slot - > out_enable [ 1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( temp_mix  >  32767 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										temp_mix  =  32767 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( temp_mix  <  - 32768 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										temp_mix  =  - 32768 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result  =  temp_mix ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ------------------------------------------------------------------------- */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ESFM_generate_stream ( esfm_chip  * chip ,  int16_t  * sndptr ,  uint32_t  num_samples )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32_t  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  num_samples ;  i + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ESFM_generate ( chip ,  sndptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sndptr  + =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}