Skip to content
Snippets Groups Projects
Select Git revision
  • 61599d4d77d0c6711c980ae98b81fbbedceb6cf6
  • master default protected
  • schneider/ir
  • rahix/user-space-ctx
  • schneider/iaq-python
  • schneider/ble-mini-demo
  • schneider/ble-ecg-stream-visu
  • schneider/mp-exception-print
  • schneider/sleep-display
  • schneider/deepsleep4
  • schneider/deepsleep2
  • schneider/deepsleep
  • schneider/ble-central
  • rahix/bluetooth-app-favorite
  • schneider/v1.17-changelog
  • schneider/ancs
  • schneider/png
  • schneider/freertos-list-debug
  • schneider/212-reset-hardware-when-entering-repl
  • schneider/bonding-fail-if-full
  • schneider/ble-fixes-2020-3
  • v1.18
  • v1.17
  • v1.16
  • v1.15
  • v1.14
  • v1.13
  • v1.12
  • v1.11
  • v1.10
  • v1.9
  • v1.8
  • v1.7
  • v1.6
  • v1.5
  • v1.4
  • v1.3
  • v1.2
  • v1.1
  • v1.0
  • release-1
41 results

menu.py

Blame
  • audio_mod.c 3.72 KiB
    #ifndef __clang__
    #pragma GCC optimize("O2")
    #endif
    
    #include <fcntl.h>
    #include <st3m_audio.h>
    #include <st3m_media.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #include "ctx.h"
    
    #define POCKETMOD_IMPLEMENTATION
    #include "pocketmod.h"
    
    typedef struct {
        st3m_media control;
        pocketmod_context pocketmod;
        uint8_t *data;
        size_t size;
        char *path;
        float scroll_pos;
    } mod_state;
    
    static void mod_draw(st3m_media *media, Ctx *ctx) {
        mod_state *self = (void *)media;
    
        ctx_rectangle(ctx, -120, -120, 240, 240);
        ctx_gray(ctx, 0);
        ctx_fill(ctx);
        // ctx_arc(ctx, 0, 0, 10, 10);
        ctx_rgb(ctx, 1.0, 1.0, 1.0);
        ctx_font_size(ctx, 20);
        char buf[100];
        sprintf(buf, "pat:%i/%i line:%i", self->pocketmod.pattern,
                self->pocketmod.num_patterns, self->pocketmod.line);
        ctx_text_align(ctx, CTX_TEXT_ALIGN_CENTER);
        ctx_move_to(ctx, 0, -20);
        ctx_text(ctx, buf);
        ctx_fill(ctx);
    
        ctx_font_size(ctx, 14);
        int xpos = 0;
        int str_width = ctx_text_width(ctx, self->path);
        if (str_width > 220) {
            xpos = ctx_sinf(self->scroll_pos) * (str_width - 220) / 2;
        }
        ctx_move_to(ctx, xpos, 14);
        ctx_gray(ctx, 0.6);
        ctx_text(ctx, self->path);
    }
    
    static void mod_think(st3m_media *media, float ms_elapsed) {
        mod_state *self = (void *)media;
        if (self->control.paused) return;
    
        if (self->control.seek == 0) {
            pocketmod_init(&self->pocketmod, self->data, self->size, 48000);
            self->control.seek = -1;
        }
    
        int samples_needed = (ms_elapsed / 1000.0) * 48000;
        if (samples_needed > 1000) samples_needed = 1000;
    
        float rendered[samples_needed * 2];
        int rend = pocketmod_render(&self->pocketmod, rendered, sizeof(rendered));
        st3m_pcm_queue_float(48000, 2, rend / (sizeof(float) * 2), rendered);
    
        if (self->control.duration == 0) {
            self->control.duration = self->pocketmod.num_patterns + 1;
        }
        if (self->pocketmod.pattern >= self->control.duration)
            self->control.duration = self->pocketmod.pattern + 1;
        self->control.position = self->pocketmod.pattern;
        if (self->pocketmod.loop_count)
            self->control.duration = self->control.position;
    
        self->scroll_pos += ms_elapsed / 1000.0;
    }
    
    static void mod_destroy(st3m_media *media) {
        mod_state *self = (void *)media;
        if (self->data) free(self->data);
        if (self->path) free(self->path);
        free(self);
    }
    
    static int file_get_contents(const char *path, uint8_t **contents,
                                 size_t *length) {
        FILE *file;
        long size;
        long remaining;
        uint8_t *buffer;
        file = fopen(path, "rb");
        if (!file) {
            return -1;
        }
        fseek(file, 0, SEEK_END);
        size = remaining = ftell(file);
    
        if (length) {
            *length = size;
        }
        rewind(file);
        buffer = malloc(size + 2);
        if (!buffer) {
            fclose(file);
            return -1;
        }
        remaining -= fread(buffer, 1, remaining, file);
        if (remaining) {
            fclose(file);
            free(buffer);
            return -1;
        }
        fclose(file);
        *contents = (unsigned char *)buffer;
        buffer[size] = 0;
        return 0;
    }
    
    st3m_media *st3m_media_load_mod(const char *path) {
        mod_state *self = (mod_state *)malloc(sizeof(mod_state));
        memset(self, 0, sizeof(mod_state));
        self->control.draw = mod_draw;
        self->control.think = mod_think;
        self->control.destroy = mod_destroy;
        self->control.has_audio = true;
        file_get_contents(path, &self->data, &self->size);
        if (!self->data ||
            !pocketmod_init(&self->pocketmod, self->data, self->size, 48000)) {
            if (self->data) free(self->data);
            free(self);
            return NULL;
        }
        self->path = strdup(path);
        self->scroll_pos = 0;
        return (st3m_media *)self;
    }