/** * \brief read data from buffer and splitting it into channels * \param bufs num_bufs float buffers, each will contain the data of one channel * \param cnt number of samples to read per channel * \param num_bufs number of channels to split the data into * \return number of samples read per channel, equals cnt unless there was too * little data in the buffer * * Assumes the data in the buffer is of type float, the number of bytes * read is res * num_bufs * sizeof(float), where res is the return value. * If there is not enough data in the buffer remaining parts will be filled * with silence. */ static int read_buffer(float **bufs, int cnt, int num_bufs) { struct deinterleave di = {bufs, num_bufs, 0, 0}; int buffered = av_fifo_size(buffer); if (cnt * sizeof(float) * num_bufs > buffered) { silence(bufs, cnt, num_bufs); cnt = buffered / sizeof(float) / num_bufs; } av_fifo_generic_read(buffer, &di, cnt * num_bufs * sizeof(float), deinterleave); return cnt; }
/** * \brief read data from buffer and splitting it into channels * \param bufs num_bufs float buffers, each will contain the data of one channel * \param cnt number of samples to read per channel * \param num_bufs number of channels to split the data into * \return number of samples read per channel, equals cnt unless there was too * little data in the buffer * * Assumes the data in the buffer is of type float, the number of bytes * read is res * num_bufs * sizeof(float), where res is the return value. * If there is not enough data in the buffer remaining parts will be filled * with silence. */ static int read_buffer(struct mp_ring *ring, float **bufs, int cnt, int num_bufs) { struct deinterleave di = { bufs, num_bufs, 0, 0 }; int buffered = mp_ring_buffered(ring); if (cnt * sizeof(float) * num_bufs > buffered) { silence(bufs, cnt, num_bufs); cnt = buffered / sizeof(float) / num_bufs; } mp_ring_read_cb(ring, &di, cnt * num_bufs * sizeof(float), deinterleave); return cnt; }
void Step:: test() { // It should keep a cache for a signal processing step (defined by an OpertionDesc). // // The cache description should contain information about what's out_of_date // and what's currently being updated. { // Create an OperationDesc pBuffer b(new Buffer(Interval(60,70), 40, 7)); for (unsigned c=0; c<b->number_of_channels (); ++c) { float *p = b->getChannel (c)->waveform_data ()->getCpuMemory (); for (int i=0; i<b->number_of_samples (); ++i) p[i] = c + 1+i/(float)b->number_of_samples (); } // Create a Step Step::ptr s2( new Step(OperationDesc::ptr())); shared_state<Step>::weak_ptr ws = s2; Step::ptr s = ws.lock (); // It should contain information about what's out_of_date and what's currently being updated. int taskid = s->registerTask(b->getInterval ()); EXCEPTION_ASSERT_EQUALS(s->not_started (), ~Intervals(b->getInterval ())); EXCEPTION_ASSERT_EQUALS(s->out_of_date(), Intervals::Intervals_ALL); Step::finishTask(s, taskid, b); EXCEPTION_ASSERT_EQUALS(s->out_of_date(), ~Intervals(b->getInterval ())); EXCEPTION_ASSERT( *b == *Step::readFixedLengthFromCache (s, b->getInterval ()) ); } // A crashed signal processing step should behave as a transparent operation. { OperationDesc::ptr silence(new Signal::OperationSetSilent(Signal::Interval(2,3))); Step s(silence); EXCEPTION_ASSERT(!s.get_crashed ()); EXCEPTION_ASSERT(s.operation_desc ()); EXCEPTION_ASSERT(s.operation_desc ().read ()->createOperation (0)); EXCEPTION_ASSERT(!dynamic_cast<Test::TransparentOperationDesc*>(s.operation_desc ().raw ())); EXCEPTION_ASSERT(!dynamic_cast<Test::TransparentOperation*>(s.operation_desc ().read ()->createOperation (0).get ())); s.mark_as_crashed_and_get_invalidator (); EXCEPTION_ASSERT(s.get_crashed ()); EXCEPTION_ASSERT(s.operation_desc ()); EXCEPTION_ASSERT(s.operation_desc ().read ()->createOperation (0)); EXCEPTION_ASSERT(dynamic_cast<Test::TransparentOperationDesc*>(s.operation_desc ().raw ())); EXCEPTION_ASSERT(dynamic_cast<Test::TransparentOperation*>(s.operation_desc ().read ()->createOperation (0).get ())); } }
/** * \brief JACK Callback function * \param nframes number of frames to fill into buffers * \param arg unused * \return currently always 0 * * Write silence into buffers if paused or an underrun occured */ static int outputaudio(jack_nframes_t nframes, void *arg) { float *bufs[MAX_CHANS]; int i; for (i = 0; i < num_ports; i++) bufs[i] = jack_port_get_buffer(ports[i], nframes); if (paused || underrun) silence(bufs, nframes, num_ports); else if (read_buffer(bufs, nframes, num_ports) < nframes) underrun = 1; if (estimate) { float now = (float)GetTimer() / 1000000.0; float diff = callback_time + callback_interval - now; if ((diff > -0.002) && (diff < 0.002)) callback_time += callback_interval; else callback_time = now; callback_interval = (float)nframes / (float)ao_data.samplerate; } return 0; }
void LADSPAPluginInstance::setIdealChannelCount(size_t channels) { if (m_audioPortsIn.size() != 1 || channels == m_instanceCount) { silence(); return ; } if (isOK()) { deactivate(); } //!!! don't we need to reallocate inputBuffers and outputBuffers? cleanup(); m_instanceCount = channels; instantiate(m_sampleRate); if (isOK()) { connectPorts(); activate(); } }
/** * \brief JACK Callback function * \param nframes number of frames to fill into buffers * \param arg unused * \return currently always 0 * * Write silence into buffers if paused or an underrun occured */ static int outputaudio(jack_nframes_t nframes, void *arg) { struct ao *ao = arg; struct priv *p = ao->priv; float *bufs[MAX_CHANS]; int i; for (i = 0; i < p->num_ports; i++) bufs[i] = jack_port_get_buffer(p->ports[i], nframes); if (p->paused || p->underrun || !p->ring) silence(bufs, nframes, p->num_ports); else if (read_buffer(p->ring, bufs, nframes, p->num_ports) < nframes) p->underrun = 1; if (p->estimate) { float now = mp_time_us() / 1000000.0; float diff = p->callback_time + p->callback_interval - now; if ((diff > -0.002) && (diff < 0.002)) p->callback_time += p->callback_interval; else p->callback_time = now; p->callback_interval = (float)nframes / (float)ao->samplerate; } return 0; }
PlayScene::PlayScene() : Scene(), lastDrawTicks(0), lastBlockMove(0), lastTickEvent(0), level(1), lines(0), score(0), blocks(NULL), background(NULL), fallingBlock(NULL), nextBlock(NULL) { Player * player = Player::get( "Player" ); if( player != NULL ) player->setEventHandler( new PlaySceneEventHandler( this ) ); else { #ifdef DEBUG1 Logger::get() << "[PlayScene] No player found. Exiting." << Logger::endl; #endif this->running = false; } // Initializing random seed srand( time(NULL) ); // Creating game song Sine instrument( Mixer::get()->getSamplingFrequency(), Mixer::get()->getChannels() ); Silence silence( Mixer::get()->getSamplingFrequency(), Mixer::get()->getChannels() ); Song * song = new Song( 120, Mixer::get()->getSamplingFrequency(), Mixer::get()->getChannels() ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'B', false, 4 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'D', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'B', false, 4 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'A', false, 4 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'A', false, 4 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'D', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'B', false, 4 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'B', false, 4 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'D', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'A', false, 4 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'A', false, 4 ), Note::Blanche ); song->mixNote( instrument, Note::getFrequency( 'D', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'D', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'F', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'A', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'A', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'G', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'F', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Noire, true ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'D', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'B', false, 4 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'B', false, 4 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Croche ); song->mixNote( instrument, Note::getFrequency( 'D', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'E', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'C', false, 5 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'A', false, 4 ), Note::Noire ); song->mixNote( instrument, Note::getFrequency( 'A', false, 4 ), Note::Blanche ); Mixer::get()->add( "BlockgameSong", song ); delete song; Mixer::get()->setRepeat( "BlockgameSong", true ); // Creating grid this->blocks = new Grid( GRID_WIDTH, GRID_HEIGHT ); this->blocks->getOrigin().moveTo( GRID_X, GRID_Y, 0.0f ); this->background = new Grid( GRID_WIDTH, GRID_HEIGHT ); this->background->getOrigin().moveTo( GRID_X, GRID_Y, -0.5f ); // Generating pieces this->fallingBlock = Piece::generate(); this->fallingBlock->getOrigin().moveTo( GRID_X, GRID_Y, 0.0f ); this->nextBlock = Piece::generate(); this->nextBlock->getOrigin().moveTo( NEXT_X, NEXT_Y, 0.0f ); // Fill background vector Point2D position( 0.0f, 0.0f ); Color backgroundColor( "ffffff" ); backgroundColor.setAlpha( 0.2f ); for( unsigned int y = 0 ; y < 20 ; y++ ) { for( unsigned int x = 0 ; x < 10 ; x++ ) { position.moveTo( x, y ); this->background->insert( new Block( position, backgroundColor ) ); } } this->updateLabels(); this->lastBlockMove = SDL_GetTicks(); Mixer::get()->play( "BlockgameSong" ); }
void savesnddialog() { sound_stop(); //Alone Coder unsigned end; //Alone Coder 0.36.7 if (savesndtype) { if (savesndtype == 1) { // wave unsigned fsize = ftell(savesnd); fseek(savesnd, 0, SEEK_SET); fsize -= sizeof wavhdr; *(unsigned*)(wavhdr+4) = fsize+0x2c-8; *(unsigned*)(wavhdr+0x28) = fsize; fwrite(wavhdr, 1, sizeof wavhdr, savesnd); MessageBox(wnd, "WAV save done", "Save sound", MB_ICONINFORMATION); } else { // vtx savesndtype = 0; u8 *newb = (u8*)malloc(vtxbuffilled); for (/*unsigned*/ end = 0; end < (int)vtxbuffilled && silence(end); end += 14); vtxbuffilled -= end; memcpy(vtxbuf, vtxbuf+end, vtxbuffilled); for (end = vtxbuffilled; end && silence(end-14); end -= 14); vtxbuffilled = end; int nrec = vtxbuffilled/14; for (int i = 0; i < nrec; i++) for (int j = 0; j < 14; j++) newb[j*nrec+i] = vtxbuf[i*14+j]; free(vtxbuf); FILE *ff = fopen("vtx.tmp", "wb"); if (!ff) return; fwrite(newb, 1, vtxbuffilled, ff); fclose(ff); STARTUPINFO si = { sizeof si }; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; PROCESS_INFORMATION pi; char Parh[] = "lha a vtx.lzh vtx.tmp"; if (CreateProcess(0, Parh, 0, 0, 0, 0, 0, 0, &si, &pi)) { WaitForSingleObject(pi.hProcess, 5000); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); DeleteFile("vtx.tmp"); } else { DeleteFile("vtx.tmp"); MessageBox(wnd, "LHA.EXE not found in %PATH%", 0, MB_ICONERROR); return; } ff = fopen("vtx.lzh", "rb"); if (!ff) return; fseek(ff, 0x22, SEEK_SET); unsigned packed = fread(newb, 1, vtxbuffilled, ff)-1; fclose(ff); DeleteFile("vtx.lzh"); DialogBox(hIn, MAKEINTRESOURCE(IDD_VTX), wnd, VtxDlg); vtxheader.sig = (vtxchip & 1) ? WORD2('y','m') : WORD2('a','y'); static u8 ste[] = { 1, 2, 0 }; vtxheader.stereo = ste[vtxchip/2]; vtxheader.ayfq = conf.sound.ayfq; vtxheader.intfq = 50; vtxheader.year = vtxyear; vtxheader.rawsize = vtxbuffilled; fwrite(&vtxheader, 1, 0x10, savesnd); fwrite(vtxname, 1, strlen(vtxname)+1, savesnd); fwrite(vtxauthor, 1, strlen(vtxauthor)+1, savesnd); fwrite(vtxsoft, 1, strlen(vtxsoft)+1, savesnd); fwrite(vtxtracker, 1, strlen(vtxtracker)+1, savesnd); fwrite(vtxcomm, 1, strlen(vtxcomm)+1, savesnd); fwrite(newb, 1, packed, savesnd); } fclose(savesnd); savesndtype = 0; } else { OPENFILENAME ofn = { 0 }; char sndsavename[0x200]; *sndsavename = 0; ofn.lStructSize = (WinVerMajor < 5) ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME); ofn.lpstrFilter = "All sound (WAV)\0*.wav\0AY sound (VTX)\0*.vtx\0"; ofn.lpstrFile = sndsavename; ofn.nMaxFile = sizeof sndsavename; ofn.lpstrTitle = "Save Sound"; ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; ofn.hwndOwner = wnd; ofn.nFilterIndex = 1; if (GetSaveFileName(&ofn)) { char *name = sndsavename; for (char *x = name; *x; x++) if (*x == '\\') name = x+1; if (!strchr(name, '.')) { if (ofn.nFilterIndex == 1) strcat(sndsavename, ".wav"); else strcat(sndsavename, ".vtx"); } savesnd = fopen(ofn.lpstrFile, "wb"); if (!savesnd) MessageBox(wnd, "Can't create file", 0, MB_ICONERROR); else if (ofn.nFilterIndex == 2) { // vtx savesndtype = 2; vtxbuf = 0; } else { // wave. all params, except fq are fixed: 16bit,stereo *(unsigned*)(wavhdr+0x18) = conf.sound.fq; // fq *(unsigned*)(wavhdr+0x1C) = conf.sound.fq*4; // bitrate fwrite(wavhdr, 1, 44, savesnd); // header savesndtype = 1; } } } eat(); sound_play(); //Alone Coder }
int main(int argc, char **argv){ SDL_AudioSpec requested, obtained; int quit = 0; int xo, yo; int i, j, k; int meter[4]; static char chars[10] = { '+', '-', '*', '#', 'X', '@', '%', '$', 'M', 'W' }; caca_display_t *dp; caca_canvas_t *cv; caca_canvas_t *pineapple; if(SDL_Init( SDL_INIT_AUDIO ) < 0){ err(1, "Couldnt initialize SDL\n"); exit(1); } cv = caca_create_canvas(80, 24); pineapple = caca_create_canvas(0, 0); if((cv == NULL) || (pineapple == NULL)){ printf("failed to create canvas\n"); return 1; } dp = caca_create_display(cv); caca_set_display_time(dp, 20000); if(dp == NULL){ printf("Failed to create display\n"); return 1; } caca_import_file(pineapple, "./pineapple", ""); atexit(SDL_Quit); requested.freq = 16000; requested.format = AUDIO_U8; requested.samples = 256; requested.callback = audiocb; requested.channels = 1; if(SDL_OpenAudio(&requested, &obtained) == -1){ err(1, "SDL_OpenAudio"); } initchip(); loadfile(argv[1]); SDL_PauseAudio(0); silence(); startplaysong(0); while(!quit) { caca_event_t ev; caca_set_color_ansi(cv, CACA_DEFAULT, CACA_DEFAULT); caca_clear_canvas(cv); xo = caca_get_canvas_width(cv); yo = caca_get_canvas_height(cv); //caca_blit(cv, 0, 0, pineapple, NULL); caca_blit(cv, 55, 0, pineapple, NULL); caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16)); caca_put_str(cv, (xo - strlen("pineapple player")) / 2, (yo / 2) - 5, "pineapple player"); caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16)); caca_printf(cv, (xo - strlen("song pos -> ")) / 2, (yo / 2) - 3, "song pos -> %x", songpos); for(i = 0; i < 4; i ++) meter[i] = (osc[i].volume*20)/255; /* note visualizer */ i = 0; for(j = 0; j < 25; j=j+6){ for(k = 0; k < 4; k++){ caca_draw_line(cv, (((xo/2)+10)-j)-k, yo, (((xo/2)+10)-j)-k, yo - meter[i], chars[caca_rand(0, 9)]); } i++; } for(i = 0; i < 4; i ++) caca_printf(cv, 0, i, "%0x", osc[i].volume); while(caca_get_event(dp, CACA_EVENT_ANY, &ev, 0)) { if(caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS) { switch(caca_get_event_key_ch(&ev)) { case 'q': case 'Q': case CACA_KEY_ESCAPE: quit = 1; break; } } } caca_refresh_display(dp); } silence(); caca_free_display(dp); caca_free_canvas(cv); return 0; }
/* vi insert mode */ void insertmode(void){ int c; currmode = PM_INSERT; drawgui(); for(;;){ if((c = getch()) != ERR) switch(c){ case KEY_ESCAPE: currmode = PM_NORMAL; return; case 'h': case KEY_LEFT: act_mvleft(); break; case 'j': case KEY_DOWN: act_mvdown(); break; case 'k': case KEY_UP: act_mvup(); break; case 'l': case KEY_RIGHT: act_mvright(); break; /* change octave */ case '<': if(octave) octave--; break; case '>': if(octave < 8) octave++; break; /* change instrument */ case CTRL('J'): if(currtab == 2){ act_viewinstrdec(); }else if(currtab == 1){ act_viewtrackdec(); } break; case CTRL('K'): if(currtab == 2){ act_viewinstrinc(); }else if(currtab == 1){ act_viewtrackinc(); } break; case '[': act_viewinstrdec(); break; case ']': act_viewinstrinc(); break; case CTRL('H'): currtab--; if(currtab < 0) currtab = 2; break; case CTRL('L'): currtab++; currtab %= 3; break; case 'Z': c = nextchar(); switch(c){ case 'Z': lft_savefile(filename); erase(); refresh(); endwin(); exit(0); break; case 'Q': erase(); refresh(); endwin(); exit(0); break; } break; case ' ': silence(); currmode = PM_NORMAL; return; case ENTER: if(currtab != 2){ if(currtab == 1){ silence(); startplaytrack(currtrack); }else if(currtab == 0){ silence(); startplaysong(songy); } } break; case '`': if(currtab == 0){ int t = tune->sng[songy].track[songx / 4]; if(t) currtrack = t; currtab = 1; }else if(currtab == 1){ currtab = 0; } break; default: _insertc(c); if(currtab == 1){ tracky+=step; tracky %= (tune->tracklen); }else if(currtab == 2){ //if(instry < instrument[currinstr].length-1) instry++; if(instrx < 2) instrx++; else instrx--; instry %= instrument[currinstr].length; } saved = 0; } drawgui(); usleep(10000); } }
/* normal mode */ void normalmode(int c){ int i; // don't save the action for repeat if it's a movement or a repeat, or // something else that doesnt make sense to repeat if(c != 'h' && c != 'j' && c != 'k' && c != 'l' && c != CTRL('D') && c != CTRL('U') && c != CTRL('H') && c != CTRL('L') && c != 'H' && c != 'M' && c != 'L' && c != 'g' && c != 'G' && c != '.'){ lastaction = c; lastrepeatnum = cmdrepeatnum; } for(i=0; i<cmdrepeatnum; i++){ switch(c){ /* add line */ case 'a': act_addline(); break; case '.': // if the last command was a replace, just insert the last thing // inserted instead of calling insertmode() if(lastaction == 'r') _insertc(lastinsert); else normalmode(lastaction); cmdrepeatnum = lastrepeatnum; break; case KEY_ESCAPE: disptick = 0; jammermode(); break; case CTRL('Y'): switch(currtab){ case 0: if(songoffs>0){ if(songy==getmaxy(stdscr)-3+songoffs) songy--; songoffs--; } break; case 1: if(trackoffs>0){ if(tracky==getmaxy(stdscr)-3+trackoffs) tracky--; trackoffs--; } break; case 2: if(instroffs>0){ if(instry==getmaxy(stdscr)-3+instroffs) instry--; instroffs--; } break; } break; case CTRL('E'): switch(currtab){ case 0: if(songy<=tune->songlen-2){ if(songy==songoffs) songy++; songoffs++; } break; case 1: if(tracky<=(tune->tracklen)-2){ if(tracky==trackoffs) tracky++; trackoffs++; } break; case 2: if(instry<=instrument[currinstr].length-2){ if(instry==instroffs) instry++; instroffs++; } break; } break; case 'H': switch(currtab){ case 0: songy = songoffs; break; case 1: tracky = trackoffs; break; case 2: instry = instroffs; break; } break; // the second cases (to the right of the colon) for M and L // took some serious guesswork, so I'm not sure if they're // correct but they seem to work. case 'M': switch(currtab){ case 0: songy = (tune->songlen <= getmaxy(stdscr)-2)? tune->songlen/2 : ((getmaxy(stdscr)-6)/2) + songoffs; break; case 1: tracky = (tune->tracklen <= getmaxy(stdscr)-2)? tune->tracklen/2 : ((getmaxy(stdscr)-6)/2) + trackoffs; break; case 2: instry = (instrument[currinstr].length <= getmaxy(stdscr)-2)? instrument[currinstr].length/2 : ((getmaxy(stdscr)-6)/2) + instroffs; break; } break; case 'L': switch(currtab){ case 0: songy = (tune->songlen <= getmaxy(stdscr)-2)? tune->songlen-1 : getmaxy(stdscr)-3+songoffs; break; case 1: tracky = (tune->tracklen <= getmaxy(stdscr)-2)? tune->tracklen-1 : getmaxy(stdscr)-3+trackoffs; break; case 2: instry = (instrument[currinstr].length <= getmaxy(stdscr)-2)? instrument[currinstr].length-1 : getmaxy(stdscr)-3+instroffs; break; } break; case 'g': if(nextchar() == 'g'){ act_mvtop(); } break; case 'G': act_mvbottom(); break; // yank case 'y': c = nextchar(); switch(c){ case 'y': //tclip = malloc(1); if(currtab == 0){ tcliplen = 1; memcpy(&tclip, &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 1; memcpy(&tclip, &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 1; memcpy(&iclip, &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; case 'j': //tclip = malloc(2); if(currtab == 0){ tcliplen = 2; memcpy(&tclip[0], &tune->sng[songy], sizeof(struct songline)); act_mvdown(); memcpy(&tclip[1], &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 2; memcpy(&tclip[0], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); act_mvdown(); memcpy(&tclip[1], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 2; memcpy(&iclip[0], &instrument[currinstr].line[instry], sizeof(struct instrline)); act_mvdown(); memcpy(&iclip[1], &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; case 'k': //tclip = malloc(2); if(currtab == 0){ tcliplen = 2; memcpy(&tclip[1], &tune->sng[songy], sizeof(struct songline)); act_mvup(); memcpy(&tclip[0], &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 2; memcpy(&tclip[1], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); act_mvup(); memcpy(&tclip[0], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 2; memcpy(&iclip[1], &instrument[currinstr].line[instry], sizeof(struct instrline)); act_mvup(); memcpy(&iclip[0], &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; } break; //paste case 'p': if(currtab == 0){ if(tune->songlen < 256){ for(int i = 0; i < tcliplen; i++){ // insert new line memmove(&tune->sng[songy + 2], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); songy++; tune->songlen++; memset(&tune->sng[songy], 0, sizeof(struct songline)); // paste to new line memcpy(&tune->sng[songy], &tclip[i], sizeof(struct songline)); } } }else if(currtab == 1){ for(int i = 0; i < tcliplen; i++){ memcpy(&tune->trk[currtrack].line[tracky], &tclip[i], sizeof(struct trackline)); if(tracky < (tune->tracklen)-step) tracky += step; else tracky = (tune->tracklen)-1; } }else if(currtab == 2){ if(instrument[currinstr].length < 256){ // insert new line for(int i = 0; i < icliplen; i++){ struct instrument *in = &instrument[currinstr]; instry++; memmove(&in->line[instry + 1], &in->line[instry + 0], sizeof(struct instrline) * (in->length - instry)); in->length++; in->line[instry].cmd = '0'; in->line[instry].param = 0; // paste to new line memcpy(&instrument[currinstr].line[instry], &iclip[i], sizeof(struct instrline)); } } //if(instry < instrument[currinstr].length-1) instry++; } break; // copy everything in the current phrase or instrument into the next free one case '^': if(currtab == 1){ f = nextfreetrack(); memcpy(&tune->trk[f], &tune->trk[currtrack], sizeof(struct track)); currtrack = f; }else if(currtab == 2){ f = nextfreeinstr(); memcpy(&instrument[f], &instrument[currinstr], sizeof(struct instrument)); currinstr = f; } break; // TODO: Y and P can be removed after we make visual mode // copy whole phrase or instrument case 'Y': if(currtab == 1){ memcpy(&tclip, &tune->trk[currtrack], sizeof(struct track)); }else if(currtab == 2){ memcpy(&iclip, &instrument[currinstr], sizeof(struct instrument)); } break; // paste whole phrase or instrument case 'P': if(currtab == 1){ memcpy(&tune->trk[currtrack], &tclip, sizeof(struct track)); }else if(currtab == 2){ memcpy(&instrument[currinstr], &iclip, sizeof(struct instrument)); } break; /* delete line */ // TODO: clean this SHIT up // TODO: add an ACT_ function for delete case 'd': c = nextchar(); switch(c){ case 'd': act_delline(); break; case 'k': if(currtab == 2){ struct instrument *in = &instrument[currinstr]; instry--; int i; for(i=0; i<2; i++){ if(in->length > 1){ memmove(&in->line[instry + 0], &in->line[instry + 1], sizeof(struct instrline) * (in->length - instry - 1)); in->length--; if(instry >= in->length) instry = in->length - 1; } } }else if(currtab == 0){ songy--; int i; for(i=0; i<2; i++){ if(tune->songlen > 1){ memmove(&tune->sng[songy + 0], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); tune->songlen--; if(songy >= tune->songlen) songy = tune->songlen - 1; } } } break; case 'j': if(currtab == 2){ struct instrument *in = &instrument[currinstr]; int i; for(i=0; i<2; i++){ if(in->length > 1){ memmove(&in->line[instry + 0], &in->line[instry + 1], sizeof(struct instrline) * (in->length - instry - 1)); in->length--; if(instry >= in->length) instry = in->length - 1; } } }else if(currtab == 0){ int i; for(i=0; i<2; i++){ if(tune->songlen > 1){ memmove(&tune->sng[songy + 0], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); tune->songlen--; if(songy >= tune->songlen) songy = tune->songlen - 1; } } } break; } break; /* undo */ case 'u': act_undo(); /* Clear */ case 'x': act_clronething(); break; case 'X': act_clritall(); break; case ENTER: if(currtab != 2){ if(currtab == 1){ silence(); startplaytrack(currtrack); }else if(currtab == 0){ silence(); startplaysong(songy); } } break; case 'Z': c = nextchar(); switch(c){ case 'Z': lft_savefile(filename); erase(); refresh(); endwin(); exit(0); break; case 'Q': erase(); refresh(); endwin(); exit(0); break; } break; /* Enter command mode */ case ':': cmdlinemode(); break; case ' ': silence(); tune->plonked = 0; break; // TODO: make an act_ function for '`' case '`': if(currtab == 0){ int t = tune->sng[songy].track[songx / 4]; if(t) currtrack = t; currtab = 1; if(playtrack){ startplaytrack(currtrack); } }else if((currtab == 1) && ((trackx == 2) || (trackx == 3))){ int i = tune->trk[currtrack].line[tracky].instr; if(i) currinstr = i; currtab = 2; } else if(currtab == 1){ currtab = 0; }else if(currtab == 2){ currtab = 1; } break; /* Enter insert mode */ case 'i': insertmode(); break; /* Enter visual mode */ case 'v': visualmode(); break; /* Enter visual line mode */ case 'V': visuallinemode(); break; /* enter jammer mode */ case CTRL('A'): jammermode(); break; /* Add new line and enter insert mode */ case 'o': act_addline(); insertmode(); break; case 'h': case KEY_LEFT: act_mvleft(); break; case 'j': case KEY_DOWN: act_mvdown(); break; case 'k': case KEY_UP: act_mvup(); break; case 'l': case KEY_RIGHT: act_mvright(); break; case '<': if(octave) octave--; break; case '>': if(octave < 8) octave++; break; case '{': if(currtrack > 1) currtrack--; break; case '}': if(currtrack < 255) currtrack++; break; case 'J': if(currtab == 0){ if( (songx%4) < 2){ act_trackdec(); }else{ act_transpdec(); } }else if(currtab == 1){ switch(trackx){ case 0: act_notedec(); break; case 1: act_octavedec(); break; case 2: act_instrdec(); break; case 3: act_instrdec(); break; case 4: act_fxdec(); break; case 5: case 6: act_paramdec(); break; case 7: act_fxdec(); break; case 8: case 9: act_paramdec(); break; default: setdisplay("in J"); break; } }else if(currtab == 2){ switch(instrx){ case 0: act_fxdec(); break; case 1: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_notedec(); }else{ act_paramdec(); } break; case 2: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_notedec(); }else{ act_paramdec(); } break; } } break; case 'K': if(currtab == 0){ if( (songx%4) < 2){ act_trackinc(); }else{ act_transpinc(); } }else if(currtab == 1){ switch(trackx){ case 0: act_noteinc(); break; case 1: act_octaveinc(); break; case 2: act_instrinc(); break; case 3: act_instrinc(); break; case 4: act_fxinc(); break; case 5: case 6: act_paraminc(); break; case 7: act_fxinc(); break; case 8: case 9: act_paraminc(); break; default: setdisplay("in K"); break; } }else if(currtab == 2){ switch(instrx){ case 0: act_fxinc(); break; case 1: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_noteinc(); }else{ act_paraminc(); } break; case 2: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_noteinc(); }else{ act_paraminc(); } break; } } break; case CTRL('J'): if(currtab == 2){ act_viewinstrdec(); }else if(currtab == 1){ act_viewtrackdec(); } break; case CTRL('K'): if(currtab == 2){ act_viewinstrinc(); }else if(currtab == 1){ act_viewtrackinc(); } break; case '[': act_viewinstrdec(); break; case ']': act_viewinstrinc(); break; case '(': callbacktime++; break; case ')': callbacktime--; break; case '-': if(step > 0) step--; break; case '=': if(step < 0x0f) step++; break; case CTRL('H'): currtab--; if(currtab < 0) currtab = 2; break; case CTRL('L'): currtab++; currtab %= 3; break; case KEY_TAB: currtab++; currtab %= 3; break; case CTRL('U'): act_bigmvup(); break; case CTRL('D'): act_bigmvdown(); break; /*case CTRL('P'): vimode = false; break;*/ // replace case 'r': _insertc(nextchar()); break; default: break; } // end switch } // end for cmdrepeatnum = 1; cmdrepeat = 0; }