Created
January 4, 2025 02:19
-
-
Save bwhitman/3c1be07f729380e9f03fd38ef2ed75aa to your computer and use it in GitHub Desktop.
playdate running AMY
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
HEAP_SIZE = 8388208 | |
STACK_SIZE = 61800 | |
PRODUCT = HelloWorld.pdx | |
# Locate the SDK | |
SDK = ${PLAYDATE_SDK_PATH} | |
ifeq ($(SDK),) | |
SDK = $(shell egrep '^\s*SDKRoot' ~/.Playdate/config | head -n 1 | cut -c9-) | |
endif | |
ifeq ($(SDK),) | |
$(error SDK path not found; set ENV value PLAYDATE_SDK_PATH) | |
endif | |
###### | |
# IMPORTANT: You must add your source folders to VPATH for make to find them | |
# ex: VPATH += src1:src2 | |
###### | |
VPATH += src | |
# List C source files here | |
SRC = src/main.c | |
SRC += $(addprefix /Users/bwhitman/outside/amy/src/, \ | |
amy.c \ | |
algorithms.c \ | |
custom.c \ | |
patches.c \ | |
delay.c \ | |
envelope.c \ | |
filters.c \ | |
oscillators.c \ | |
transfer.c \ | |
sequencer.c \ | |
partials.c \ | |
pcm.c \ | |
log2_exp2.c \ | |
) | |
# List all user directories here | |
UINCDIR = /Users/bwhitman/outside/amy/src/ | |
# List user asm files | |
UASRC = | |
# List all user C define here, like -D_DEBUG=1 | |
UDEFS = -Wno-strict-aliasing -Wextra -Wno-unused-parameter -Wpointer-arith \ | |
-Wno-float-conversion -Wno-missing-declarations -Wno-strict-prototypes -Wno-double-promotion \ | |
-Wno-old-style-declaration | |
# Define ASM defines here | |
UADEFS = | |
# List the user directory to look for the libraries here | |
ULIBDIR = | |
# List all user libraries here | |
ULIBS = --specs=nosys.specs | |
include $(SDK)/C_API/buildsupport/common.mk | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.c | |
// Extension | |
// | |
// Created by Dave Hayden on 7/30/14. | |
// Copyright (c) 2014 Panic, Inc. All rights reserved. | |
// | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include "pd_api.h" | |
#include "amy.h" | |
#include "examples.h" | |
static int update(void* userdata); | |
const char* fontpath = "/System/Fonts/Asheville-Sans-14-Bold.pft"; | |
LCDFont* font = NULL; | |
// Context state for audio callback | |
typedef struct { | |
PlaydateAPI *pd; | |
SoundSource *source; | |
} AudioState; | |
void example_juno_note() { | |
struct event e = amy_default_event(); | |
e.load_patch = 0; | |
strcpy(e.voices, "0"); | |
amy_add_event(e); | |
e = amy_default_event(); | |
strcpy(e.voices, "0"); | |
e.midi_note = 50; | |
e.velocity = 1; | |
e.time = 1000; | |
amy_add_event(e); | |
} | |
// I've seen frame counts as big as 1440, I think *8 is enough room (2048) | |
#define OUTPUT_RING_FRAMES (AMY_BLOCK_SIZE*8) | |
#define OUTPUT_RING_LENGTH (OUTPUT_RING_FRAMES*AMY_NCHANS) | |
int16_t output_ring[OUTPUT_RING_LENGTH]; | |
uint16_t ring_write_ptr = AMY_BLOCK_SIZE*AMY_NCHANS; // start after one AMY frame | |
uint16_t ring_read_ptr = 0 ; | |
uint16_t in_ptr = 0; | |
extern int16_t amy_in_block[AMY_BLOCK_SIZE*AMY_NCHANS]; | |
// https://devforum.play.date/t/tips-and-tricks-for-processing-audio-in-c/8025/5 | |
int amy_callback(void* context, int16_t* left, int16_t* right, int len) { | |
// We lag a AMY block behind input here because our frame size is never a multiple of AMY block size | |
for(uint16_t frame=0;frame<len;frame++) { | |
in_ptr+=2; // stereo | |
if(in_ptr == (AMY_BLOCK_SIZE*2)) { // we have a block of input ready | |
// render and copy into output ring buffer | |
int16_t * buf = amy_simple_fill_buffer(); | |
// reset the input pointer for future input data | |
in_ptr = 0; | |
// copy this output to a ring buffer | |
for(uint16_t amy_frame=0;amy_frame<AMY_BLOCK_SIZE;amy_frame++) { | |
output_ring[ring_write_ptr++] = buf[AMY_NCHANS * amy_frame + 0]; | |
output_ring[ring_write_ptr++] = buf[AMY_NCHANS * amy_frame + 1]; | |
if(ring_write_ptr == OUTPUT_RING_LENGTH) ring_write_ptr = 0; | |
} | |
} | |
// Per audio frame, copy (lagged by AMY_BLOCK_SIZE) output data from AMY into expected audio out buffer | |
left[frame] = output_ring[ring_read_ptr++]; | |
right[frame] = output_ring[ring_read_ptr++]; | |
if(ring_read_ptr == OUTPUT_RING_LENGTH ) ring_read_ptr = 0; | |
} | |
return 1; | |
} | |
#ifdef _WINDLL | |
__declspec(dllexport) | |
#endif | |
int eventHandler(PlaydateAPI* pd, PDSystemEvent event, uint32_t arg) | |
{ | |
(void)arg; // arg is currently only used for event = kEventKeyPressed | |
if ( event == kEventInit ) | |
{ | |
amy_start(1,1,1,1); | |
example_juno_note(); | |
// Create a new audio source with a state context | |
AudioState *state = pd->system->realloc(NULL, sizeof (AudioState)); | |
state->pd = pd; | |
state->source = pd->sound->addSource(&amy_callback, state, 1); | |
const char* err; | |
font = pd->graphics->loadFont(fontpath, &err); | |
if ( font == NULL ) | |
pd->system->error("%s:%i Couldn't load font %s: %s", __FILE__, __LINE__, fontpath, err); | |
// Note: If you set an update callback in the kEventInit handler, the system assumes the game is pure C and doesn't run any Lua code in the game | |
pd->system->setUpdateCallback(update, pd); | |
} | |
return 0; | |
} | |
#define TEXT_WIDTH 86 | |
#define TEXT_HEIGHT 16 | |
int x = (400-TEXT_WIDTH)/2; | |
int y = (240-TEXT_HEIGHT)/2; | |
int dx = 1; | |
int dy = 2; | |
static int update(void* userdata) | |
{ | |
PlaydateAPI* pd = userdata; | |
pd->graphics->clear(kColorWhite); | |
pd->graphics->setFont(font); | |
pd->graphics->drawText("Hello World!", strlen("Hello World!"), kASCIIEncoding, x, y); | |
x += dx; | |
y += dy; | |
if ( x < 0 || x > LCD_COLUMNS - TEXT_WIDTH ) | |
dx = -dx; | |
if ( y < 0 || y > LCD_ROWS - TEXT_HEIGHT ) | |
dy = -dy; | |
pd->system->drawFPS(0,0); | |
return 1; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment