/*! @function midi_start @abstract @discussion @param @result */ void midi_start() { Pm_Initialize(); Pt_Start(1, NULL, NULL); retval = Pm_OpenOutput(&mstream, 0,NULL,512,NULL,NULL,0); if(retval != pmNoError) { printf("error: %s \n", Pm_GetErrorText(retval)); } else /* set channel 1 to grand piano */ program_change(1, 1); }
int init_alsa(ALSA_SEQ* seq, unsigned char verbose) { if ( verbose) printf("Setting up alsa\n"); seq->g_seq = open_client(); if (seq->g_seq == NULL) { if ( verbose >= 0) printf("Error: open_client failed.\n"); return 0; } int my_client_id = snd_seq_client_id(seq->g_seq); seq->g_port = my_new_port(seq->g_seq); if ( verbose) printf("client:port = %i:%i\n", my_client_id, seq->g_port); program_change(seq->g_seq, seq->g_port, 9, 0); int ret = 1; notedown_alsa((void*)seq, 9, 57, 55); if ( verbose) printf("Returning %i\n", ret); return ret; }
int main(int argc, char ** argv) { static msg_block_t msg; memset((void *)&msg, 0, sizeof(msg)); struct timespec time; double time0, time1; uint32_t notes[SCALE_PATTERN][NOTES_SIZE]; uint32_t scales[SCALE_PATTERN][SCALE_SIZE] = { {0,4,7,9,}, {0,5,7,9,}, {2,4,7,11,}, {2,5,7,9,}, {2,5,7,11,}, {0,2,4,7,}, {0,2,5,7,}, {0,2,5,9,}, }; uint32_t instruments[] = { 0, 4, 5, 6, 8, 9, 11, 14, 15, 16, 17, 19, 24, 25, 26, 30, 40, 42, 46, 48, 51, 52, 56, 57, 60, 61, 63, 64, 65, 68, 69, 70, 73, 88, 89, 91, 93, 94, 95, 98, 99, 103, 104, 110, }; uint32_t insts = sizeof(instruments) / sizeof(uint32_t); int fb = open(FBDEV, O_RDWR); if (fb > 0) { struct fb_fix_screeninfo fbfsi; struct fb_var_screeninfo fbvsi; if (ioctl(fb, FBIOGET_FSCREENINFO, &fbfsi) == 0) { msg.fbinfo.smem_start = fbfsi.smem_start; msg.fbinfo.smem_len = fbfsi.smem_len; msg.fbinfo.line_length = fbfsi.line_length; } if (ioctl(fb, FBIOGET_VSCREENINFO, &fbvsi) == 0) { msg.fbinfo.xres = fbvsi.xres; msg.fbinfo.yres = fbvsi.yres; msg.fbinfo.xres_virtual = fbvsi.xres_virtual; msg.fbinfo.yres_virtual = fbvsi.yres_virtual; msg.fbinfo.xoffset = fbvsi.xoffset; msg.fbinfo.yoffset = fbvsi.yoffset; msg.fbinfo.bits_per_pixel = fbvsi.bits_per_pixel; } close(fb); } long pagesize = (sysconf(_SC_PAGESIZE)); int fdmem = open(MEMDEV, O_RDWR | O_SYNC); uint32_t *frame_buffer = NULL; size_t mapsize = 0; if ((fdmem > 0) && (msg.fbinfo.smem_start != 0)) { off_t physical_page = msg.fbinfo.smem_start & (~(pagesize - 1)); unsigned long offset = msg.fbinfo.smem_start - (unsigned long)physical_page; mapsize = msg.fbinfo.smem_len + offset; frame_buffer = mmap(NULL, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fdmem, physical_page); if (frame_buffer == MAP_FAILED) { perror("Framebuffer Map Failed"); } } struct timespec time_start; clock_gettime(CLOCK_MONOTONIC_RAW, &time_start); srand((uint32_t)time_start.tv_nsec); seq_context_t seq; if (open_sequencer(&seq) == FALSE) { exit(EXIT_FAILURE); } program_change(&seq, 0, 48); control_change(&seq, 0, 91, 127); static rt_context_t rtx; memset((void *)&rtx, 0, sizeof(rtx)); int width = msg.fbinfo.xres_virtual; int height = msg.fbinfo.yres_virtual; rtx.objnum = OBJNUM; rtx.light.pos = vec3_set(-4.0f, 8.0f, 2.0f); rtx.light.col = vec3_set(1.0f, 1.0f, 1.0f); rtx.eye = vec3_set(0.0f, 0.0f, -7.0f); rtx.swidth = 10.0f * (float)width / (float)height; rtx.sheight = 10.0f; rtx.width = width / SCALE; rtx.height = height / SCALE; rtx.xoff = 0; rtx.yoff = 0; rtx.ax = rtx.swidth / (float)rtx.width; rtx.ayc = rtx.sheight / (float)rtx.height; rtx.ay = rtx.sheight / (float)rtx.height; uint32_t i, j; for (i = 0; i < SCALE_PATTERN; i++) { for (j = 0; j < NOTES_SIZE; j++) { notes[i][j] = scales[i][j % SCALE_SIZE] + (j / SCALE_SIZE) * 12; } } for (i = 0; i < rtx.objnum; i++) { rtx.obj[i].type = SPHERE; rtx.obj[i].pos = vec3_set(0.0f, -100.0f, 0.0f); rtx.obj[i].rad = 1.0f; rtx.obj[i].col = vec3_set(randf(), randf(), randf()); rtx.obj[i].flag_shadow = TRUE; rtx.obj[i].flag_refrect = TRUE; rtx.obj[i].spd = vec3_set(0.0f, 0.0f, 0.0f); rtx.obj[i].note = 0; } rtx.obj[0].type = PLANE; rtx.obj[0].norm = normalize(vec3_set(0.0f, 1.0f, 0.0f)); rtx.obj[0].dist = 2.0f; rtx.obj[0].col = vec3_set(0.1f, 0.3f, 0.6f); rtx.obj[0].flag_shadow = TRUE; rtx.obj[0].flag_refrect = TRUE; rtx.obj[0].spd = vec3_set(0.0f, 0.0f, 0.0f); uint32_t scale = 0; uint32_t curobj = 0; float next_note_time = get_elapsed(time_start) + 3.0f; float next_scale_time = get_elapsed(time_start) + 15.0f + randf() * 15.0f; float time_now = get_elapsed(time_start); float time_quit = time_now + 3600.0f; uint32_t retry_count = 0; uint32_t counter = 0; float time_prev = 0.0f; while(time_now < time_quit) { uint32_t e; for (e = 1; e < rtx.objnum; e++) { rtx.obj[e].pos = vec3_add(rtx.obj[e].pos, rtx.obj[e].spd); } time_now = get_elapsed(time_start); if (time_now > next_note_time) { e = (curobj % (rtx.objnum - 1)) + 1; rtx.obj[e].pos = vec3_set(randf()*8.0f-4.0f, randf()*6.0f-1.0f, randf()*8.0+0.0f); rtx.obj[e].col = vec3_set(randf(), randf(), randf()); rtx.obj[e].spd = vec3_set(randf()*0.1f-0.05f,randf()*0.1f-0.05f,randf()*0.1f-0.05f); note_off(&seq, 0, rtx.obj[e].note); rtx.obj[e].note = notes[scale][(uint32_t)(randf() * 17.0f) + 12]; note_on(&seq, 0, rtx.obj[e].note, 127 - rtx.obj[e].note); curobj++; float len = (randf() + 0.5f); next_note_time = time_now + len * len * len; } if (time_now > next_scale_time) { scale = (uint32_t)(randf() * (float)SCALE_PATTERN); program_change(&seq, 0, instruments[(uint32_t)(randf() * ((float)insts + 0.99f))]); rtx.obj[0].col = vec3_set(randf(), randf(), randf()); rtx.light.pos = vec3_set(randf() * 8.0f - 4.0f, 8.0f, randf() * 4.0f); next_scale_time = time_now + (randf() + 0.1f) * 40.0f; } render(&msg, &rtx, frame_buffer); counter++; if (counter > 100) { //printf("FPS: %.2f\n", 100.0f / (time_now - time_prev)); time_prev = time_now; counter = 0; } } close_sequencer(&seq); munmap(frame_buffer, mapsize); close(fdmem); return 0; }
Tset keypress(Tset vars) { // Declare an integer variable assign the value of the users key press to it. int input; input = getch(); /* * Use a switch to check if the key pressed corresponds to any control keys and if * so edit the approriate variable. */ switch(input) { case '1': { vars.instl_velocity = 0; break; } case 'q': { vars.instc_velocity = 0; break; } case 'a': { vars.instb_velocity = 0; break; } case 'z': { vars.drum_vel = 0; break; } case '3': { vars.instl_velocity += 5; break; } case 'e': { vars.instc_velocity += 5; break; } case 'd': { vars.instb_velocity += 5; break; } case 'c': { vars.drum_vel += 5; break; } /* * In cases where velocity is decreased check that the decreased value does not go * negative before decreasing the variable. */ case '2': { if(vars.instl_velocity - 5 > 0) vars.instl_velocity -= 5; break; } case 'w': { if(vars.instc_velocity - 5 > 0) vars.instc_velocity -= 5; break; } case 's': { if(vars.instb_velocity - 5 > 0) vars.instb_velocity -= 5; break; } case 'x': { if(vars.drum_vel - 5 > 0) vars.drum_vel -= 5; break; } // Set the instruments velocitys to be at a standard value declared in the header file case '4': { vars.instl_velocity = LEAD; break; } case 'r': { vars.instc_velocity = CHORD; break; } case 'f': { vars.instb_velocity = BASS; fflush(stdin); break; } case 'v': { vars.drum_vel = DRUM; break; } /* * In cases where tempo is decreased check that the decreased value does not go negative * before decreasing the variable. */ case 'o': { if(vars.tempo - 2 > 0) vars.tempo--; break; } case 'i': { vars.tempo ++; break; } // This sets the variable loop to 1, stopping the main loop and terminating the program. case ' ': { vars.loop = 1; break; } case '5': { /* * When changing the instrument the variable scroll checks which instrument * is currently playing, changes it to the next instrument and adds 1 to scroll. * At the last instrument scroll is reset and so as the key 5 is repeatedly pressed * its cycles through the possible instruments. */ switch(vars.instl_scroll) { case 0: { program_change(1, 5); vars.instl_scroll++; break; } case 1: { program_change(1, 31); vars.instl_scroll++; break; } case 2: { program_change(1, 27); vars.instl_scroll++; break; } case 3: { program_change(1, 67); vars.instl_scroll++; break; } case 4: { program_change(1, 10); vars.instl_scroll = 5; break; } case 5: { program_change(1, 115); vars.instl_scroll = 0; break; } } break; } case 't': { switch(vars.instc_scroll) { case 0: { program_change(2, 5); vars.instc_scroll++; break; } case 1: { program_change(2, 27); vars.instc_scroll++; break; } case 2: { program_change(2, 29 ); vars.instc_scroll = 0; break; } } break; } case 'g': { switch(vars.instb_scroll) { case 0: { program_change(3, 33); vars.instb_scroll++; break; } case 1: { program_change(3, 34); vars.instb_scroll = 0; break; } } break; } case 'l': { vars.key++; break; } case 'k': { vars.key--; break; } /* * Here the user has chosen to restart the program so turn off all midi notes, * clear the screen and print a message. Calls the user input functions * again and display the user input messages. */ case 8: { midi_note(vars.oldlead, 1, 0); midi_note(vars.key, 1, 0); midi_note(vars.oldbass, 3, 0); midi_note(vars.key, 3, 0); midi_note(vars.key, 2, 0); midi_note(vars.key + 7, 2, 0); midi_note(vars.key + 9, 2, 0); midi_note(vars.key + 10, 2, 0); midi_note(vars.key + 12, 2, 0); midi_note(vars.key + 15, 2, 0); midi_note(vars.key + 16, 2, 0); system ("cls"); printf("Starting again...\n\nRe-enter values:\n\n"); vars.rhythm = rhythm(); vars.key = pitch(); vars.tempo = speed(); vars = input_instrument(vars); vars.loop = 0; vars.time = 0; vars.count = 0; vars.luck = 0; vars.shift = 0; messages( vars); break; } /* * Here the user is changing the rhythm so set the key back to its original value, * reset shift, time and count and set the variable rhythm to the approriate value. */ case '8': { vars.key = vars.original; vars.shift = 0; vars.rhythm = 1; vars.time = 0; vars.count = 0; break; } case '9': { vars.key = vars.original; vars.shift = 0; vars.rhythm = 2; vars.time = 0; vars.count = 0; break; } case '0': { vars.key = vars.original; vars.shift = 0; vars.rhythm = 3; vars.time = 0; vars.count = 0; break; } } fflush(stdin); // Clear the standard input memory return(vars); // Return the altered vars }
void add_sequence() { // Declare and initiate local variables int count; char key[2]; int instrument; int number; int channel; count = 0; instrument = -1; number = -1; // Clear the screen clrscr(); // While user input is not in expected range prompt user for key do { fflush(stdin); printf("Assign sequence to which key? [Q W E R T Y]: "); scanf("%s", &key[0]); if((key[0] != 'q' && key[0] != 'w' && key[0] != 'e' && key[0] != 'r' && key[0] != 't' && key[0] != 'y') || key[1] != '\0') printf("Invalid character\n\n"); } while((key[0] != 'q' && key[0] != 'w' && key[0] != 'e' && key[0] != 'r' && key[0] != 't' && key[0] != 'y') || key[1] != '\0'); // While user input is not in expected range prompt user for instrument while(instrument < 0 || instrument > 127) { printf("Choose instrument [0 - 127]: "); scanf("%d", &instrument); if(instrument < 0 || instrument > 127) printf("Invalid character\n\n"); } // While user input is not in expected range prompt user for number of notes in sequence while(number < 0) { printf("Number of notes in sequence: "); scanf("%d", &number); if(number < 0) printf("Invalid character\n\n"); } // Create a structure of type note_info and assign the pointer current to it current = (note_info*)malloc(sizeof(note_info)); /* * Depending on which key the sequence is to be assigned to remove any seqeunce * previously associated with the key, set the appropriate channel and assign the * appropriate first pointer to the current structure */ switch(key[0]) { case 'q': { freelist(&first_q); channel = 1; first_q = current; break; } case 'w': { freelist(&first_w); channel = 2; first_w = current; break; } case 'e': { freelist(&first_e); channel = 3; first_e = current; break; } case 'r': { freelist(&first_r); channel = 4; first_r = current; break; } case 't': { freelist(&first_t); channel = 5; first_t = current; break; } case 'y': { freelist(&first_y); channel = 6; first_y = current; break; } } // Assign the chosen instrument to the channel program_change(channel, instrument); // Clear the screen, prompt the user for note information and initiate variables clrscr(); printf("Enter pitch, velocity and duration of notes. Enter 0 velocity for rests:\n"); current->pitch = -1; current->velocity = -1; current->duration = -1; // Create a loop which cycles while count is lower than the number of notes in sequence chosen by the user while(count < number) { // Increment count each cycle count++; // While user input is not in expected range prompt user for Pitch while((current->pitch < 0) || (current->pitch > 127)) { printf("\nPitch: "); scanf("%d", ¤t->pitch); if((current->pitch < 0) || (current->pitch > 127)) printf("Invalid character\n"); } // While user input is not in expected range prompt user for Velocity while((current->velocity < 0) || (current->velocity > 127)) { printf("Velocity: "); scanf("%d", ¤t->velocity); if((current->velocity < 0) || (current->velocity > 127)) printf("Invalid character\n\n"); } // While user input is not in expected range prompt user for Duration while(current->duration < 1) { printf("Duration: "); scanf("%d", ¤t->duration); if(current->duration < 1) printf("Invalid character\n\n"); } // Assign the chosen channel to the channel in the current structure current->channel = channel; /* * If not at the end of the sequence set the previous pointer to the current structure, * create a new structure the assign the pointer next in previous to the new structure */ if(count < number) { previous = current; current = (note_info*)malloc(sizeof(note_info)); previous->next = current; } // If at the end of the sequence set the next pointer to Null else current->next = NULL; } return; }