示例#1
0
文件: player.cpp 项目: biemme14/gdemu
void loop()
{
  prog_uchar *pc;
  long started = millis();
  int ticks = 0;
  for (pc = mont; pc < mont + sizeof(mont);) {
    byte cmd = pgm_read_byte_near(pc++);  // upper 2 bits are command code
    if ((cmd & 0xc0) == 0) {
      // Command 0x00: pause N*5 milliseconds
      ticks += (cmd & 63);
      while (millis() < (started + ticks * 5)) {
        adsr();
        delay(1);
      }
    } else {
      byte v = (cmd & 63);
      byte a;
      if ((cmd & 0xc0) == 0x40) {
        // Command 0x40: silence voice
        target[v] = 0;
      } else if ((cmd & 0xc0) == 0x80) {
        // Command 0x80: set voice frequency and amplitude
        byte flo = pgm_read_byte_near(pc++);
        byte fhi = pgm_read_byte_near(pc++);
        GD.__wstart(VOICES + 4 * v);
        SPI.transfer(flo);
        SPI.transfer(fhi);
        GD.__end();
        target[v] = pgm_read_byte_near(pc++);
      }
    }
  }
}
示例#2
0
文件: general.c 项目: sooda/spankmoog
sample eval_channel(Channel* ch) {
	const Instrument* instr = ch->instr;
	sample a = instr->oscfunc(instr, ch->instrstate, ch->note);
	sample b = instr->filtfunc(instr, ch->instrstate, a);
	sample c = adsr(&instr->adsr, &ch->adsr) * b;
	if (ch->adsr.section == ADSR_OFF)
		ch->alive = 0;
	return ch->volume * c;
}
示例#3
0
文件: Test_all.cpp 项目: eriser/CSL
void test_envelope() {
	Sine vox(220);
	float duration = 3.0;	// time
	float attack = 0.06;		// time
	float decay = 0.1;		// time
	float sustain = 0.1;		// value
	float release = 1.5;		// time
	ADSR adsr(duration, attack, decay, sustain, release);
	MulOp mul(vox, adsr);
	logMsg("playing sin ADSR envelope.");
	adsr.trigger();	
	run_test(mul);
	logMsg("sin ADSR evelope done.");
	
	Sine vox2(220);
	ADSR adsr2(duration, attack, decay, sustain, release);
	vox2.set_scale(adsr2);
	logMsg("playing sin ADSR envelope.");
//	adsr.dump();
	adsr2.trigger();	
	run_test(vox2);
	logMsg("sin ADSR evelope done.");
}
示例#4
0
int syna_get(void *tune)
{
    int     n=0,i,j,tmp,a,d,s,r,mod,sweep,
            wave=0,patt,track,note;
    char    *rows[MAXR],*key,*tnp;

    module=tune;
#ifndef TINY
    cleanshit(module);  /* You better have a clean module in intros... */
#endif

    /* Extract rows */
    for(n=0;n<MAXR;n++)
    {
        rows[n]=strtok((n)?NULL:module,"\n");
        if(rows[n]==NULL)
            break;
    }

    /* Extract data from rows */
    for(i=0;i<n;i++)
    {
        if(rows[i][0]=='#')
            continue;

        if(key=strtok(rows[i],":"))
        {
            if(!strcmp(key,"bpm"))
            {
                tmp=atoi(strtok(NULL,":"))*10/25;
                update=6*global/tmp;
                ekolen=update*3;
            }
            if(key[0]=='i')
            {
                /* Get instrument number and wave form */
                tmp=atoi(&key[1]);
                echo[tmp]=malloc(ekolen*sizeof(float));
                tnp=strtok(NULL,",");
                if(!strcmp(tnp,"kantti"))
                    wave=0;
                if(!strcmp(tnp,"sini"))
                    wave=1;
                if(!strcmp(tnp,"saha"))
                    wave=2;
                if(!strcmp(tnp,"kohina"))
                    wave=3;
                
                /* Get ADSR */
                a=atoi(strtok(NULL,","));
                d=atoi(strtok(NULL,","));
                s=atoi(strtok(NULL,","));
                r=atoi(strtok(NULL,","));
                len[tmp]=a+d+s+r+1;
                instr[tmp]=malloc(len[tmp]*sizeof(float));

                mod=atoi(strtok(NULL,","));
                if(tnp=strtok(NULL,","))
                    sweep=atoi(tnp);
                else
                    sweep=0;
                if(tnp=strtok(NULL,","))
                    pan[tmp]=(float)atoi(tnp)/100.0;
                if(tnp=strtok(NULL,","))
                    pola[tmp]=(float)atoi(tnp)/100.0;

                adsr(a,d,s,r,mod,sweep,tmp,wave);
            }

            if(key[0]=='p') /* Handle pattern */
            {
                patt=atoi(&key[1]);
                j=0;
                while(1)
                {
                    tnp=strtok(NULL,",");
                    if(tnp!=NULL)
                    {
                        note=0;
                        for(tmp=0;notes[tmp][0]!='0';tmp++)
                            if(!strcmp(notes[tmp],tnp))
                                note=notei[tmp];
                        ptn[patt][j]=note;
                        if(note==VOL || note==SLIDE)
                        {
                            j++;
                            ptn[patt][j]=atoi(strtok(NULL,","));
                        }

                        j++;
                    }
                    else
                    {
                        ptn[patt][j]=END;
                        break;
                    }
                }
            }

            if(key[0]=='t') /* Handle track */
            {
                track=atoi(&key[1]);
                j=0;
                while(1)
                {
                    tnp=strtok(NULL,",");
                    if(tnp!=NULL)
                    {
                        if(!strcmp(tnp,"loop"))
                            trak[track][j]=LOOP;
                        else
                        {
                            patt=atoi(&tnp[1]);
                            trak[track][j]=patt;
                        }
                        j++;
                    }
                    else
                    {
                        trak[track][j]=END;
                        break;
                    }
                }
            }
        }
    }

    return(0);
}
示例#5
0
// This function read instrument data and outputs info on the screen or on the verbose file
// it's not actually needed to convert the data to SF2 format, but is very useful for debugging
static void verbose_instrument(const inst_data inst, bool recursive)
{
	// Do nothing with unused instruments
	if(!force_output_unused && inst.word0 == 0x3c01 && inst.word1 == 0x02 && inst.word2 == 0x0F0000) return;

	uint8_t instr_type = inst.word0 & 0xff;
	fprintf(out_txt, "  Type : 0x%x  ", instr_type);
	switch(instr_type)
	{	
		// Sampled instruments
		case 0 :
		case 8 :
		case 0x10 :
		case 0x18 :
		case 0x20 :
		case 0x28 :
		case 0x30 :
		case 0x38 :
		{
			uint32_t sadr = inst.word1 & 0x3ffffff;
			fprintf(out_txt, "(sample @0x%x)\n", sadr);

			try
			{
				if(fseek(inGBA, sadr, SEEK_SET)) throw -1;
				struct
				{
					uint32_t loop;
					uint32_t pitch;
					uint32_t loop_pos;
					uint32_t len;
				}
				ins;
				fread(&ins, 4, 4, inGBA);

				fprintf(out_txt, "      Pitch : %u\n", ins.pitch/1024);
				fprintf(out_txt, "      Length : %u\n", ins.len);

				if(ins.loop == 0)
					fputs("      Not looped\n", out_txt);
				else if(ins.loop == 0x40000000)
					fprintf(out_txt, "      Loop enabled at : %u\n", ins.loop_pos);
				else if(ins.loop == 0x1)
					fputs("      BDPCM compressed\n", out_txt);
				else
					fputs("      Unknown loop type\n", out_txt);

				adsr(inst.word2);
			}
			catch (...)
			{
				fputs("Invalid instrument (an exception occured)", out_txt);
			}
		}	break;

		// Pulse channel 1 instruments
		case 1 :
		case 9 :
		{
			fputs("(GB pulse channel 1)", out_txt);
			if((char)inst.word0 != 8)			// Display sweep if enabled on GB channel 1
				fprintf(out_txt, "      Sweep : 0x%x\n", inst.word0 & 0xFF);

			adsr(inst.word2);
			duty_cycle(inst.word1);
		}	break;
		
		// Pulse channel 2 instruments
		case 2 :
		case 10 :
		case 18 :
		{
			fputs("(GB pulse channel 2)", out_txt);
			adsr(inst.word2);
			duty_cycle(inst.word1);
		}	break;

		// Channel 3 instruments
		case 3 :
		case 11 :
		{
			fputs("(GB channel 3)", out_txt);
			adsr(inst.word2);
			fputs("      Waveform : ", out_txt);

			try
			{
				// Seek to waveform's location
				if(fseek(inGBA, inst.word1&0x3ffffff, SEEK_SET)) throw -1;
				int waveform[32];

				for(int j=0; j<16; j++)
				{
					uint8_t a = fgetc(inGBA);
					waveform[2*j] = a>>4;
					waveform[2*j+1] = a & 0xF;
				}

				// Display waveform in text format
				for(int j=7; j>=0; j--)
				{
					for(int k=0; k!=32; k++)
					{
						if(waveform[k] == 2*j)
							fputc('_', out_txt);
						else if(waveform[k] == 2*j+1)
							fputc('-', out_txt);
						else
							fputc(' ', out_txt);
					}
					fputc('\n', out_txt);
				}
			}
			catch(...)
			{
				fputs("Invalid instrument (an exception occured)", out_txt);
			}
		}	break;

		// Noise instruments
		case 4 :
		case 12 :
			fputs("(GB noise channel 4)", out_txt);
			adsr(inst.word2);
			if(inst.word1  == 0)
				fputs("      long random sequence\n", out_txt);
			else
				fputs("      short random sequence\n", out_txt);
			break;

		// Key-split instruments
		case 0x40 :
			fputs("Key-split instrument", out_txt);

			if(!recursive)
			{
				bool *keys_used = new bool[128]();
				try
				{
				// seek to key table's location
					if(fseek(inGBA, inst.word2&0x3ffffff, SEEK_SET)) throw -1;

					for(int k = 0; k!= 128; k++)
					{
						uint8_t c = fgetc(inGBA);
						if(c & 0x80) continue;		// Ignore entries with MSB set (invalid)
						keys_used[c] = true;
					}

					int instr_table = inst.word1 & 0x3ffffff;

					for(int k = 0; k!= 128; k++)
					{
						// Decode instruments used at least once in the key table
						if(keys_used[k])
						{
							try
							{
								// Seek to the addressed instrument
								if(fseek(inGBA, instr_table + 12*k, SEEK_SET)) throw -1;
								inst_data sub_instr;
								// Read the addressed instrument
								fread(&sub_instr, 4, 3, inGBA);
	
								fprintf(out_txt, "\n      Sub_intrument %d", k);
								verbose_instrument(sub_instr, true);
							}
							catch(...)
							{
								fputs("Invalid sub-instrument (an exception occurred)", out_txt);
							}
						}
					}
				}
				catch (...)
				{}
				delete[] keys_used;
			}
			else
				fputs("   Illegal double-recursive instrument !", out_txt);
			break;

		// Every key split instruments
		case 0x80 :
			fputs("Every key split instrument", out_txt);

			if(!recursive)
			{
				uint32_t address = inst.word1 & 0x3ffffff;
				for(int k = 0; k<128; ++k)
				{
					try
					{
						if(fseek(inGBA, address + k*12, SEEK_SET)) throw -1;
						inst_data key_instr;
						fread(&key_instr, 4, 3, inGBA);
						
						fprintf(out_txt, "\n   Key %d", k);
						verbose_instrument(key_instr, true);
					}
					catch(...)
					{
						fputs("Illegal sub-instrument (an exception occured)", out_txt);
					}
				}
			}
			else	// Prevent instruments with multiple recursivities
				fputs("   Illegal double-recursive instrument !", out_txt);
			break;

		default :
			fputs("Unknown instrument type", out_txt);
			return;
	}
	if(recursive)
		fprintf(out_txt, "      Key : %d, Pan : %d\n", (inst.word1>>8) & 0xFF, inst.word1>>24);
}
示例#6
0
/*This routine is the HNIC. It determines when all the subroutines run.
Messing with business in here can have lethal consequences for many things, particularly 
related to timing.	What needs to run when is one of the greatest challenges of this design.
*/
int main(void)
{
	
	
	MIDI_MESSAGE mm_incoming_message;
	MIDI_MESSAGE *p_mm_incoming_message = &mm_incoming_message;

	p_global_setting = &global_setting;//assign the pointer to point at the global_setting structure

	static unsigned char uc_aux_task_state;//keep track of auxilliary task state - filter, lfo, envelope


	cli();//disable interrupts
  	sys_init();
	sei();//enable interrupts

	initialize_pots(p_global_setting);

	/*Initialize global_settings.
	This routine sets some important initial values. Without them, some of the subroutines
	can be confused because they are expecting certain 0 points that indicate some function is
	not active.*/
	global_setting.auc_synth_params[ADSR_SUSTAIN] = 92;
	global_setting.auc_synth_params[ADSR_LENGTH] = 127;
	decode_adsr_length(p_global_setting, 127);
	global_setting.auc_synth_params[ADSR_DECAY] = 127;
	global_setting.auc_synth_params[ADSR_RELEASE] = 127;
	global_setting.auc_ad_values[PITCH_SHIFT] = 127;
	global_setting.auc_synth_params[PITCH_SHIFT] = 127;
	global_setting.auc_parameter_source[PITCH_SHIFT] = SOURCE_AD;
	global_setting.auc_ad_values[AMPLITUDE] = 192;
	global_setting.auc_synth_params[AMPLITUDE] = 255;//set amplitude
	global_setting.auc_parameter_source[AMPLITUDE] = SOURCE_AD;
	global_setting.uc_adsr_multiplier = ADSR_MIN_VALUE;//Initialize the ADSR to its minimum value
	global_setting.auc_synth_params[PORTAMENTO] = 0;
	global_setting.auc_synth_params[FILTER_ENV_AMT] = 128;
	global_setting.auc_synth_params[OSC_MIX] = 127;
	global_setting.auc_synth_params[OSC_2_WAVESHAPE] = SQUARE;

  for (; ;)
  { 
  	RESET_WATCHDOG;

	/*Has the slow interrupt occurred?*/
	if(1 == g_uc_slow_interrupt_flag)
	{

		//Calculate the adsr envelope value
		adsr(p_global_setting);

		//Set the amplitude of the Voltage-Controlled Amplifier
		set_amplitude(p_global_setting);
		
		if(g_un_switch_debounce_timer > 0)
		{
			g_un_switch_debounce_timer--;
		}
		else if(g_uc_ext_int_0_flag ==  TRUE)
		{
			led_switch_handler(p_global_setting, TACT_LFO_SHAPE);
			g_uc_ext_int_0_flag = FALSE;
			CLEAR_EXT_INTERRUPTS;
			ENABLE_EXT_INT_0;
		}
		else if(g_uc_ext_int_1_flag == TRUE)
		{
			led_switch_handler(p_global_setting, TACT_LFO_DEST);
			g_uc_ext_int_1_flag = FALSE;
			CLEAR_EXT_INTERRUPTS
			ENABLE_EXT_INT_1;
		}

		//Let's handle midi messages.
		//We have to check the receive uart.
		//If there is data in the uart receive buffer, check to see
		//if the incoming fifo has anything in it.  If it doesn't have midi messages
		//waiting to be handled, send it to the incoming midi handler routine. 
		//If there is stuff in the incoming midi fifo, put the new message next in the fifo.
		if(uart_rx_buffer_has_byte())
		{
			handle_incoming_midi_byte(uart_get_byte());
		}

		/*auxilliary tasks
		These tasks are handled one at a time, each time through the slow interrupt routine
		We have to do them one at a time because we can't do them all every time through the loop
		because we don't have enough clock cycles, nor do we really need to do them that way
		They are contained in a state machine
		The number of things to do here affects the timing of them.  Adding more things to do will affect timing
		Just think about it a minute before you do anything crazy like that, but if you must and if you want the 
		envelopes and LFOs to work at specific frequency then 
		you'll have to go through each of the things below
		*/
		switch(uc_aux_task_state)
		{
			case AUX_TASK_SPI:
			/*The SPI is shared by the i/o expanders and the digital pots of the 
			filter. These tasks are mutually exclusive though, only one at a time.*/

			    spi();

				uc_aux_task_state = AUX_TASK_READ_AD;				

			break;

			case AUX_TASK_READ_AD:

				if(!CHECK_BIT(ADCSRA, ADSC))
				{
						read_ad(p_global_setting);
						g_uc_ad_ready_flag = 0;
				}
				
				uc_aux_task_state = AUX_TASK_CALC_PITCH;	

			break;

			case AUX_TASK_CALC_PITCH:

				calculate_pitch(p_global_setting);
				uc_aux_task_state = AUX_TASK_LFO;

			break;
	
			case AUX_TASK_LFO:
				
				lfo(p_global_setting);				
				uc_aux_task_state = AUX_TASK_MIDI;

			break;

			case AUX_TASK_MIDI:
					
				//If there are midi messages in the incoming message fifo, handle them.
				if(g_uc_midi_messages_in_incoming_fifo > 0)
				{
					get_midi_message_from_incoming_fifo(p_mm_incoming_message);
					midi_interpret_incoming_message(p_mm_incoming_message, p_global_setting);
				}
				
				uc_aux_task_state = AUX_TASK_SPI;

			break;

			default:

			break;


			}//Case statement end

		//clear the slow interrupt flag
		g_uc_slow_interrupt_flag = 0;
	}
	
	
  }//for Loop end

  return 0;
  }
示例#7
0
文件: main.cpp 项目: Ooya/M2-IMAGINA
FMOD_RESULT F_CALLBACK cb_question1 (FMOD_SOUND *sound, void *data, unsigned int datalen)
{
    unsigned int  count;
    static float  t = 0;
    signed short *stereo16bitbuffer = (signed short *)data;

    for (count=0; count<datalen>>2; count++)
    {
	// un échantillon à gauche puis à droite (format "signed short" = entier entre -32768 et 32767)

        *stereo16bitbuffer++ = (signed short) (ampGauche * sin(2 * PI * freq * t * distorsion)*32767*adsr(t));
        *stereo16bitbuffer++ = (signed short) (ampDroite * sin(2 * PI * freq * t * distorsion)*32767*adsr(t));
	    t += (1.0f/44100.0f);
    }

    return FMOD_OK;
}
示例#8
0
文件: main.cpp 项目: znoraka/master2
FMOD_RESULT F_CALLBACK cb_question2 (FMOD_SOUND *sound, void *data, unsigned int datalen)
{
    unsigned int  count;
    signed short *stereo16bitbuffer = (signed short *)data;
    static float t;
    for (count=0; count<datalen>>2; count++)
    {

      
      *stereo16bitbuffer++ = (signed short) (sin(M_PI * 2.0f * freq * t) * 32768.0f * ampGauche * adsr(t));
      *stereo16bitbuffer++ = (signed short) (sin(M_PI * 2.0f * freq * t) * 32768.0f * ampDroite * adsr(t));
      t += 1.0f/44100.0f;
    }

    return FMOD_OK;
}