20 Commits

Author SHA1 Message Date
c4f56bfd20 Update src/main.cpp 2025-10-23 20:02:12 -04:00
87826ac9c8 remove debug print 2024-05-01 00:44:04 -05:00
86557d9cf4 scope adjustments 2024-05-01 00:42:53 -05:00
5cc62a1bfc remove bufbuf 2024-04-24 13:54:19 -05:00
27d3e61d59 remove scope shadow 2024-04-24 13:44:10 -05:00
a745768f9b redo scope, fix warning on strings 2024-04-11 17:09:59 -05:00
544396d82e Add default build directory 2024-04-11 17:04:40 -05:00
cac554cc1c stabilize scope more 2024-03-21 19:05:27 -05:00
f8b286e169 set effects show to false by default 2024-03-21 13:29:58 -05:00
b278e686dd add argument for toggling existing options 2024-03-21 13:29:30 -05:00
0f8efdb537 Add option to disable pattern 2024-03-21 13:25:55 -05:00
05b44db876 adjusted scope lerp 2024-03-21 13:12:32 -05:00
a4e3734568 replace channel bar page with scope/waveform 2024-03-20 19:07:36 -05:00
f97e50612f Fix issue with adding octave over line and disable dynamic roll not disabling the octave line 2024-02-27 22:24:07 -06:00
29c8a8a4ad Up octave number on Piano Roll 2024-02-27 22:13:29 -06:00
1144735efa Correct height of piano roll display 2024-02-27 21:25:07 -06:00
876efb2e8f Update AUR pkgbuild 2024-02-27 21:19:41 -06:00
3b09077e4c Fixed my goddamn rebasing 2024-02-27 21:16:00 -06:00
b57095ead6 Add octaves to Piano Roll 2024-02-27 18:02:49 -06:00
b57f03f963 Alter Pattern VU meters 2024-02-26 20:16:24 -06:00
4 changed files with 187 additions and 74 deletions

View File

@@ -3,6 +3,7 @@ project(trakker)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED True)
SET(CMAKE_CXX_FLAGS "-O3")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
include_directories(${CMAKE_BINARY_DIR})
find_package(Git)
find_package(ALSA REQUIRED)

View File

@@ -1,12 +1,12 @@
# Maintainer: wirlaburla <wirlaburla@worlio.com>
# Maintainer: Nick G. <wirlaburla@worlio.com>
pkgname=trakker-git
pkgver=0.3.0.r1.ge275e29
pkgver=0.5.2.r3.gf97e506
pkgrel=1
pkgdesc=''
arch=('x86_64' 'aarch64')
url='https://codeberg.org/Wirlaburla/trakker'
license=(GPL3)
pkgdesc='A terminal-based tracker interface for libxmp.'
arch=('x86_64')
url='https://git.worlio.com/Wirlaburla/trakker'
license=('GPL3')
depends=('alsa-lib' 'libxmp' 'ncurses')
makedepends=('git' 'cmake')
provides=('trakker')
@@ -15,8 +15,8 @@ source=("$pkgname::git+$url.git#branch=master")
sha256sums=('SKIP')
pkgver() {
cd $pkgname
git describe --long --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g'
cd "$pkgname"
git describe --long --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
}
prepare() {

View File

@@ -12,17 +12,16 @@
#include "trakker.h"
#include "trakker_version.h"
#define SAMPLERATE 48000
#define BUFFER_SIZE 250000
static std::string note_name[] = { "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B " };
static std::string pages[] = { "1. Info", "2. Pattern", "3. Bars", "4. Piano Roll", "5. Config", "6. Help" };
static char* device = "default";
static std::string pages[] = { "1. Info", "2. Pattern", "3. Scope", "4. Piano Roll", "5. Config", "6. Help" };
static const char* device = "default";
snd_pcm_hw_params_t *hwparams;
char* file;
bool colorMode = 0; // 0 - Auto, 1 - Monochrome, 2 - 8-bit, 3 - Full
int mtype = XMP_MODE_AUTO;
int smix = 70;
int srate = 48000;
int display = 0;
int mode = 0;
int vol;
@@ -38,6 +37,7 @@ bool loop;
bool ptnChans = true;
bool dynamicRoll = true;
bool ptnOrder = true;
bool showEffects = false;
std::map<int, char> efxtable;
std::map<int, bool> efxmemtable;
@@ -48,13 +48,15 @@ int main(int argc, char *argv[]) {
printf("\n");
printf("Help\n");
printf("-h Show this message.\n");
printf("-d <num> Start on the specified panel.\n");
printf("-c <num> Force terminal color mode.\n");
printf(" 0 Auto (default)\n");
printf(" 1 Monochrome\n");
printf(" 2 8bit\n");
printf(" 3 Full\n");
printf("-d <num> Start on the specified panel.\n");
printf("-o <num> Toggle player options\n");
printf("-s <num> Stereo Seperation\n");
printf("-r <num> Sample rate (default 48000)\n");
exit(0);
} else if (strcmp(argv[a], "-d") == 0) {
int newdisplay = atoi(argv[a+1])-1;
@@ -68,6 +70,22 @@ int main(int argc, char *argv[]) {
} else if (strcmp(argv[a], "-c") == 0) {
colorMode = atoi(argv[a+1]);
a++;
} else if (strcmp(argv[a], "-o") == 0) {
switch (atoi(argv[a+1])) {
case 1:
ptnChans = !ptnChans;
break;
case 2:
dynamicRoll = !dynamicRoll;
break;
case 3:
ptnOrder = !ptnOrder;
break;
case 4:
showEffects = !showEffects;
break;
}
a++;
} else if (strcmp(argv[a], "-s") == 0) {
int newmix = atoi(argv[a+1]);
if (newmix > 100 || newmix < 0)
@@ -101,6 +119,15 @@ int main(int argc, char *argv[]) {
mtype = XMP_MODE_ITSMP;
}
a++;
} else if (strcmp(argv[a], "-r") == 0) {
int newrate = atoi(argv[a+1]);
if (newrate > 192000 || newrate < 48000)
fprintf(stderr, "Sample rate argument is invalid.\n");
else {
printf("Setting sample rate to %dkHz\n", newrate/1000);
srate = newrate;
}
a++;
} else if (!file) {
file = argv[a];
} else {
@@ -110,13 +137,42 @@ int main(int argc, char *argv[]) {
}
int err;
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
fprintf(stderr, "Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
unsigned int chan, rate;
unsigned int btime = 250000; /* 250ms */
unsigned int ptime = 50000; /* 50ms */
char *card_name = "default";
if ((err = snd_pcm_open(&handle, card_name,
SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
fprintf(stderr, "Unable to initialize ALSA pcm device: %s\n",
snd_strerror(err));
return -1;
}
if ((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 2, SAMPLERATE, 1, BUFFER_SIZE)) < 0) {
fprintf(stderr, "Playback open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
chan = 2;
rate = 48000;
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_hw_params_any(handle, hwparams);
snd_pcm_hw_params_set_access(handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16);
snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0);
snd_pcm_hw_params_set_channels_near(handle, hwparams, &chan);
snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &btime, 0);
snd_pcm_hw_params_set_period_time_near(handle, hwparams, &ptime, 0);
snd_pcm_nonblock(handle, 0);
if ((err = snd_pcm_hw_params(handle, hwparams)) < 0) {
fprintf(stderr, "Unable to set ALSA output parameters: %s\n",
snd_strerror(err));
return -1;
}
if ((err = snd_pcm_prepare(handle)) < 0) {
fprintf(stderr, "Unable to prepare ALSA: %s\n",
snd_strerror(err));
return -1;
}
printf("%s initialized.\n", "ALSA");
@@ -232,17 +288,21 @@ int main(int argc, char *argv[]) {
row = pos = -1;
generateEffectsTable(xmi.mod->type);
xmp_set_player(xc, XMP_PLAYER_MODE, mtype);
xmp_start_player(xc, SAMPLERATE, 0);
if ((err = xmp_start_player(xc, 48000, 0)) != 0) {
if ((err = xmp_start_player(xc, 44100, 0)) != 0) {
fprintf(stderr, "Failed to start player: %d\n", err);
exit(EXIT_FAILURE);
}
}
xmp_set_player(xc, XMP_PLAYER_MIX, smix);
int key;
bool displayChanged;
displayChanged = true;
while (true) {
while (xmp_play_frame(xc) == 0) {
xmp_get_frame_info(xc, &xfi);
if (xmp_play_frame(xc) != 0 && !stopped) break;
if (xfi.loop_count > looped && !loop) break;
else looped = xfi.loop_count;
if (xfi.loop_count > looped && !loop) break;
else looped = xfi.loop_count;
keys:
timeout(stopped?-1:0);
@@ -331,6 +391,9 @@ int main(int argc, char *argv[]) {
case '3':
ptnOrder = !ptnOrder;
break;
case '4':
showEffects = !showEffects;
break;
}
}
break;
@@ -437,7 +500,7 @@ void displayHeader(xmp_module_info *mi, xmp_frame_info *fi) {
} else if (display == 1) {
displayPatterns(mi, fi);
} else if (display == 2) {
displayVolumes(mi, fi);
displayScope(mi, fi);
} else if (display == 3) {
displayNoteRoll(mi, fi);
} else if (display == 4) {
@@ -472,7 +535,7 @@ void displayInfo(xmp_module_info *mi, xmp_frame_info *fi) {
}
void displayPatterns(xmp_module_info *mi, xmp_frame_info *fi) {
int chnsize = 15;
int chnsize = showEffects?15:11;
if (ptnOrder) {
for (int j = 0; j < mi->mod->len; j++) {
if (mi->mod->xxo[j] == 0xFF) continue;
@@ -493,22 +556,24 @@ void displayPatterns(xmp_module_info *mi, xmp_frame_info *fi) {
wmove(dis, 0, cxpos);
for (int i = 0; i < mi->mod->chn; i++) {
struct xmp_channel_info cinfo = fi->channel_info[i];
int voll = (cinfo.volume * (256-cinfo.pan)/256)*2;
if (voll >= 64) wattron(dis, volhi);
int voll = (cinfo.volume * (256-cinfo.pan)/256);
if (voll >= 48) wattron(dis, volhi);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, volhi);
if (voll >= 48) wattron(dis, volmd);
if (voll >= 32) wattron(dis, volmd);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, volmd);
if (voll >= 32) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
if (voll >= 16) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
if (voll > 0) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
if (showEffects) {
if (voll >= 8) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
if (voll > 0) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
}
wattron(dis, chnvw);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
@@ -520,20 +585,22 @@ void displayPatterns(xmp_module_info *mi, xmp_frame_info *fi) {
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, chnvw);
int volr = (cinfo.volume * cinfo.pan/256)*2;
if (volr > 0) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
int volr = (cinfo.volume * cinfo.pan/256);
if (showEffects) {
if (volr > 0) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
if (volr >= 8) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
}
if (volr >= 16) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
if (volr >= 32) wattron(dis, vollo);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, vollo);
if (volr >= 48) wattron(dis, volmd);
if (volr >= 32) wattron(dis, volmd);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, volmd);
if (volr >= 64) wattron(dis, volhi);
if (volr >= 48) wattron(dis, volhi);
mvwaddch(dis, 0, (cxpos++)-hOffset, ' ');
wattroff(dis, volhi);
@@ -579,11 +646,13 @@ void displayPatterns(xmp_module_info *mi, xmp_frame_info *fi) {
else if (event.note > 0 && event.note <= 0x80)
snprintf(vol, 4, "v40");
else snprintf(vol, 4, "...");
char f1;
if ((efxmemtable[event.fxt] || event.fxp != 0) && (f1 = efxtable[event.fxt]) != NULL) snprintf(efx, 4, "%c%02X", f1, event.fxp);
else snprintf(efx, 4, "...");
sprintf(lnbuf, "|%s %s %s %s", note, ins, vol, efx);
if (showEffects) {
char f1;
if ((efxmemtable[event.fxt] || event.fxp != 0) && (f1 = efxtable[event.fxt])) snprintf(efx, 4, "%c%02X", f1, event.fxp);
else snprintf(efx, 4, "...");
sprintf(lnbuf, "|%s %s %s %s", note, ins, vol, efx);
} else sprintf(lnbuf, "|%s %s %s", note, ins, vol);
for (int z = 0; z < chnsize; z++) {
if (((i*chnsize)+2+z)-hOffset < 2) continue;
mvwaddch(dis, y, ((i*chnsize)+2+z)-hOffset, lnbuf[z]);
@@ -599,21 +668,50 @@ void displayPatterns(xmp_module_info *mi, xmp_frame_info *fi) {
}
}
void displayVolumes(xmp_module_info *mi, xmp_frame_info *fi) {
int chns = mi->mod->chn;
chtype no_pair = COLOR_PAIR(5);
for (int y = vOffset; y < chns; y++) {
if (y > (LINES - 4)+vOffset || y < 0) continue;
struct xmp_channel_info cinfo = fi->channel_info[y];
if (y > (LINES - 3)+vOffset) break;
wmove(dis, y-vOffset, 0);
int cvol = (cinfo.volume * (COLS - 5)) / (64 * (vol / 100));
wattron(dis, no_pair);
wprintw(dis, "%02X", y);
wattroff(dis, no_pair);
for (int c = 0; c < COLS - 5; c++) {
if (c < cvol) waddstr(dis, "#");
else waddstr(dis, " ");
int lerp (int a, int b, float f) {
return a + f * (b - a);
}
#include <vector>
std::vector<int> bufbufmin;
std::vector<int> bufbufmax;
void displayScope(xmp_module_info *mi, xmp_frame_info *fi) {
const char* xbuf = (char*)fi->buffer;
int percol = (fi->buffer_size/(COLS-2));
bufbufmin.resize(COLS-2);
bufbufmax.resize(COLS-2);
for (int s = 0; s < COLS-2; s++) {
int min = 0;
int max = 0;
for (int v = 0; v < percol; v++) {
int val = xbuf[(s*percol)+v];
if (val > max || max == 0) max = val;
if (val < min || min == 0) min = val;
}
// if (ln >= 0xFF) ln = 0xFF;
// else if (ln <= -0xFF) ln = -0xFF;
bufbufmin[s] = (lerp(min, bufbufmin[s-1], 0.2f) / percol)*2;
bufbufmax[s] = (lerp(max, bufbufmax[s-1], 0.2f) / percol)*2;
}
wmove(dis, 0, 0);
for (int t = 0; t < COLS-2; t++) {
int n = bufbufmin[t];
int x = bufbufmax[t];
//(1.0*(bufbufmax[t]+0xFF)/512)*(LINES-4)
for (int h = n; h <= x; h++) {
if (h >= (LINES-4) || h <= -(LINES-4)) continue;
wmove(dis, ((LINES-4)/2)+(1.0*h), t);
chtype pixpair = COLOR_PAIR(11);
if (h == n)
pixpair = COLOR_PAIR(12);
else if (h == x)
pixpair = COLOR_PAIR(10);
wattron(dis, pixpair);
waddch(dis, ' ');
wattroff(dis, pixpair);
}
}
}
@@ -621,12 +719,24 @@ void displayVolumes(xmp_module_info *mi, xmp_frame_info *fi) {
void displayNoteRoll(xmp_module_info *mi, xmp_frame_info *fi) {
int ins = mi->mod->ins;
chtype no_pair = COLOR_PAIR(5);
if (dynamicRoll) {
for (int l = 1; l <= 8; l++) {
int cnote = (l*12);
if (cnote <= prMin && l == (prMin / 12)) {
wmove(dis, 0, 0);
wprintw(dis, "<%i", l);
} else if (cnote < prMax && cnote > prMin) {
wmove(dis, 0, (((cnote - prMin) * (COLS - 5)) / (prMax - prMin))+3);
wprintw(dis, "%i", l);
}
}
}
for (int y = vOffset; y < ins; y++) {
if (!dynamicRoll) { prMin = 0; prMax = 144; }
if (y > (LINES - 5)+vOffset || y < 0) continue;
wmove(dis, y-vOffset, 0);
if (y > (LINES - (5+dynamicRoll))+vOffset || y < 0) continue;
wmove(dis, (y-vOffset)+dynamicRoll, 0);
wattron(dis, no_pair);
wprintw(dis, "%02X", y);
wprintw(dis, "%02X", y+1);
wattroff(dis, no_pair);
wclrtoeol(dis);
for (int c = 0; c < mi->mod->chn; c++) {
@@ -642,12 +752,12 @@ void displayNoteRoll(xmp_module_info *mi, xmp_frame_info *fi) {
int note = ((cinfo.note - prMin) * (COLS - 5)) / (dynamicRoll?(prMax - prMin):96);
if (cinfo.instrument != y) continue;
wmove(dis, y-vOffset, note+3);
wmove(dis, (y-vOffset)+dynamicRoll, note+3);
if (cinfo.volume >= 32)
waddstr(dis, "#");
else if (cinfo.volume >= 16 && (char)mvwinch(dis, y-vOffset, note+3) != '#')
else if (cinfo.volume >= 16 && (char)mvwinch(dis, (y-vOffset)+dynamicRoll, note+3) != '#')
waddstr(dis, "=");
else if (cinfo.volume > 0 && ((char)mvwinch(dis, y-vOffset, note+3) != '-' || (char)mvwinch(dis, y-vOffset, note+3) != '#'))
else if (cinfo.volume > 0 && ((char)mvwinch(dis, (y-vOffset)+dynamicRoll, note+3) != '-' || (char)mvwinch(dis, (y-vOffset)+dynamicRoll, note+3) != '#'))
waddstr(dis, "-");
}
wmove(dis, y, COLS-4);
@@ -663,6 +773,7 @@ void displayPlayer() {
mvwaddstr(dis, 5-vOffset, 1, "1. Pattern Channels");
mvwaddstr(dis, 6-vOffset, 1, "2. Dynamic Note Roll");
mvwaddstr(dis, 7-vOffset, 1, "3. Pattern Order");
mvwaddstr(dis, 8-vOffset, 1, "4. Pattern Effects");
wattroff(dis, A_BOLD);
mvwaddstr(dis, 1-vOffset, 20, loop?"[ #] YES":"[# ] NO");
@@ -672,6 +783,7 @@ void displayPlayer() {
mvwaddstr(dis, 5-vOffset, 22, ptnChans?"[ #] YES":"[# ] NO");
mvwaddstr(dis, 6-vOffset, 22, dynamicRoll?"[ #] YES":"[# ] NO");
mvwaddstr(dis, 7-vOffset, 22, ptnOrder?"[ #] YES":"[# ] NO");
mvwaddstr(dis, 8-vOffset, 22, showEffects?"[ #] YES":"[# ] NO");
}
void displayHelp() {
@@ -922,7 +1034,7 @@ void addToEffects(int id, char efx, bool mem) {
efxmemtable[id] = mem;
}
bool isPartOf(char* w1, char* w2) {
bool isPartOf(char* w1, const char* w2) {
int i=0;
int j=0;
while(w1[i]!='\0'){

View File

@@ -12,12 +12,12 @@ void createWindows();
void displayHeader(xmp_module_info *mi, xmp_frame_info *fi);
void displayInfo(xmp_module_info *mi, xmp_frame_info *fi);
void displayPatterns(xmp_module_info *mi, xmp_frame_info *fi);
void displayVolumes(xmp_module_info *mi, xmp_frame_info *fi);
void displayScope(xmp_module_info *mi, xmp_frame_info *fi);
void displayNoteRoll(xmp_module_info *mi, xmp_frame_info *fi);
void displayPlayer();
void displayHelp();
void generateEffectsTable(char* type);
void addToEffects(int id, char efx, bool mem);
bool isPartOf(char* w1, char* w2);
bool isPartOf(char* w1, const char* w2);
#endif