From 4bd262e766a930b2e878acfd4dfc006827c11d21 Mon Sep 17 00:00:00 2001 From: slack Date: Sat, 29 Aug 2009 22:01:31 +0200 Subject: [PATCH 1/1] Initial commit --- Makefile | 29 +++++ dl_init.c | 55 ++++++++ dl_init.h | 80 ++++++++++++ floatfucker.py | 26 ++++ gz-stub | 6 + main.c | 52 ++++++++ pack.sh | 7 ++ play.c | 229 ++++++++++++++++++++++++++++++++++ play.h | 27 ++++ song.h | 80 ++++++++++++ sstrip | Bin 0 -> 15916 bytes sstrip.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++ synth.c | 183 +++++++++++++++++++++++++++ synth.h | 74 +++++++++++ 14 files changed, 1180 insertions(+) create mode 100644 Makefile create mode 100644 dl_init.c create mode 100644 dl_init.h create mode 100755 floatfucker.py create mode 100644 gz-stub create mode 100644 main.c create mode 100755 pack.sh create mode 100644 play.c create mode 100644 play.h create mode 100644 song.h create mode 100755 sstrip create mode 100644 sstrip.c create mode 100644 synth.c create mode 100644 synth.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..13e9174 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +#CC=/home/slack/temp/gcc4/bin/gcc +CFLAGS=-m32 -Os -std=c99 -fomit-frame-pointer -ffast-math -Wall -DX86_ASM \ + $(shell sdl-config --cflags) -fno-strict-aliasing #-DDEBUG + +LDFLAGS=-m32 -nostdlib -nostartfiles -ldl -lpthread -lm + +all: main + ./pack.sh main + +main: main.o dl_init.o + $(CC) $(LDFLAGS) -o $@ $^ + ls -l main + +synth.o: synth.c synth.h + $(CC) $(CFLAGS) -c -o $@ $< + +main.o: main.c play.c + $(CC) $(CFLAGS) -c -o $@ $< + +dl_init.o: dl_init.c dl_init.h + $(CC) $(CFLAGS) -c -o $@ $< + #nasm -O9 -f elf -o $@ $< + + +clean: + rm -f *.o main intro intro.gz *~ + +.PHONY: clean + diff --git a/dl_init.c b/dl_init.c new file mode 100644 index 0000000..79ddf34 --- /dev/null +++ b/dl_init.c @@ -0,0 +1,55 @@ +#include "dl_init.h" +#include + +FN_STRUCT fn; + +char *names="libSDL-1.2.so.0\0SDL_Init\0SDL_Quit\0SDL_OpenAudio\0" + "SDL_PauseAudio\0SDL_SetVideoMode\0SDL_PollEvent\0" + "SDL_GL_SetAttribute\0SDL_GL_SwapBuffers\0SDL_GetTicks\0" + "SDL_ShowCursor\0" + + "libm.so\0powf\0fmodf\0"//expf\0" + + "libc.so.6\0rand\0srand\0time\0" + + "libGL.so\0glBegin\0glEnd\0glColor4f\0glVertex3fv\0glRotatef\0" + "glEnable\0glMatrixMode\0glLoadIdentity\0glClear\0" + "glBlendFunc\0glTranslatef\0glPushMatrix\0glPopMatrix\0glRectf\0" + "glClearColor\0glXUseXFont\0glRasterPos2f\0glCallLists\0" + + "libGLU.so\0gluPerspective\0gluLookAt\0" + + "libX11.so\0XOpenDisplay\0XLoadQueryFont\0" + + "\0"; + + +void dl_init(void) +{ + char *p=names; + void **pfn=(void **)&fn; + void *handle, *tmp; + + while(*p) + { + tmp = dlopen(p, RTLD_LAZY); + if (tmp == NULL) + { + *pfn=dlsym(handle, p); + #ifdef DEBUG + __builtin_printf("%s = %p\n", p, *pfn); + #endif + ++pfn; + } + else + { + handle=tmp; + #ifdef DEBUG + __builtin_printf("%s = %p\n", p, handle); + #endif + } + while(*p++); // Avanzamos p hasta la siguiente + } +} + + diff --git a/dl_init.h b/dl_init.h new file mode 100644 index 0000000..d407485 --- /dev/null +++ b/dl_init.h @@ -0,0 +1,80 @@ +#ifndef DL_INIT_H +#define DL_INIT_H + +#include "SDL.h" +#include +#include + +typedef struct +{ + // libSDL + int (*SDL_Init)(Uint32); + void (*SDL_Quit)(void); + int (*SDL_OpenAudio)(SDL_AudioSpec*, SDL_AudioSpec*); + + //void (*SDL_CloseAudio)(void); + void (*SDL_PauseAudio)(int); + SDL_Surface *(*SDL_SetVideoMode)(int, int, int, Uint32); + int (*SDL_PollEvent)(SDL_Event*); + int (*SDL_GL_SetAttribute)(SDL_GLattr, int); + void (*SDL_GL_SwapBuffers)(void); + Uint32 (*SDL_GetTicks)(); + int (*SDL_ShowCursor)(int); + + // libm + float (*powf)(float, float); + float (*fmodf)(float, float); + //float (*expf)(float); + + // libc + int (*rand)(void); + void (*srand)(unsigned int); + time_t (*time)(time_t*); + + // libGL + void (*glBegin)(GLenum); + void (*glEnd)(void); + void (*glColor4f)(GLfloat, GLfloat, GLfloat, GLfloat); + //void (*glVertex3f)(GLfloat, GLfloat, GLfloat); + void (*glVertex3fv)(const GLfloat*); + void (*glRotatef)(GLfloat, GLfloat, GLfloat, GLfloat); + void (*glEnable)(GLenum); + //void (*glDisable)(GLenum); + void (*glMatrixMode)(GLenum); + void (*glLoadIdentity)(void); + void (*glClear)(GLbitfield); + //void (*glScalef)(GLfloat, GLfloat, GLfloat); + void (*glBlendFunc)(GLenum, GLenum); + void (*glTranslatef)(GLfloat, GLfloat, GLfloat); + //void (*glNormal3f)(GLfloat, GLfloat, GLfloat); + //void (*glTexGeni)(GLenum, GLenum, GLint); + //void (*glGetFloatv)(GLenum, GLfloat *); + void (*glPushMatrix)(void); + void (*glPopMatrix)(void); + //void (*glTexCoord2f)(GLfloat, GLfloat); + //void (*glBindTexture)(GLenum, GLuint); + //void (*glGenTextures)(GLsizei, GLuint *); + void (*glRectf)(GLfloat, GLfloat, GLfloat, GLfloat); + void (*glClearColor)(GLfloat, GLfloat, GLfloat, GLfloat); + void (*glXUseXFont)(Font, int, int, int); + void (*glRasterPos2f)(GLfloat, GLfloat); + void (*glCallLists)(GLsizei, GLenum, const GLvoid *); + + // libGLU + void (*gluPerspective)(GLdouble, GLdouble, GLdouble, GLdouble); + void (*gluLookAt)(GLdouble, GLdouble, GLdouble, + GLdouble, GLdouble, GLdouble, + GLdouble, GLdouble, GLdouble); + //GLint (*gluBuild2DMipmaps)(GLenum, GLint, GLsizei, GLsizei, + // GLenum, GLenum, const void *); + + // libX11.so + Display* (*XOpenDisplay)(int); + XFontStruct* (*XLoadQueryFont)(Display*, char *); + +} FN_STRUCT; + +extern void dl_init(void); +extern FN_STRUCT fn; + +#endif//DL_INIT_H diff --git a/floatfucker.py b/floatfucker.py new file mode 100755 index 0000000..885a9c2 --- /dev/null +++ b/floatfucker.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +# floatfucker.py by slack/Necrostudios +# it now rounds instead of truncating (thanks iq :) + +import re +import sys +from struct import pack, unpack + +def trunc_float(f): + return unpack("f",pack("I", (unpack("I",pack("f",f))[0]+0x8000)&0xFFFF0000))[0] + +def repl_float(m): + s = m.group() + try: + f = float(s[:-1]) + except: + print "ERROR ----> ", s + return s + f2 = trunc_float(f) + return str(f2)+"f" + +float_re = re.compile("(([+-]|)\d*\.\d+|\d+\.\d*)f", re.I) + +src = file(sys.argv[1]).read() +dst = float_re.sub(repl_float, src) +file(sys.argv[2],"w").write(dst) diff --git a/gz-stub b/gz-stub new file mode 100644 index 0000000..baf34c0 --- /dev/null +++ b/gz-stub @@ -0,0 +1,6 @@ +a=/tmp/a +tail -n+7 $0|zcat>$a +chmod +x $a +$a +rm $a +exit diff --git a/main.c b/main.c new file mode 100644 index 0000000..74711c8 --- /dev/null +++ b/main.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "dl_init.h" + +//#define sin(x) __builtin_sinf(x) +//#define cos(x) __builtin_cosf(x) +//#define sqrt(x) __builtin_sqrtf(x) +//#define expf(x) __builtin_expf(x) + +float current_t; + +#ifdef DEBUG +int main() +#else +void __attribute__((externally_visible)) _start(void) +#endif +{ + SDL_Event event; + dl_init(); + + fn.SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO); + fn.SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); + fn.SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,1); + fn.SDL_SetVideoMode(1280,960,32,SDL_OPENGL); + fn.SDL_ShowCursor(0); + + while(1) + { + current_t = fn.SDL_GetTicks()/1000.0f; + while(fn.SDL_PollEvent(&event)) + { + if (event.type == SDL_KEYDOWN) + goto end; + } + + fn.SDL_GL_SwapBuffers(); + } + +end: + fn.SDL_Quit(); + +#if 1 + __asm__("xorl %eax, %eax\n\t" + "incl %eax\n\t" + "int $0x80\n\t"); +#else + exit(0); +#endif +} + diff --git a/pack.sh b/pack.sh new file mode 100755 index 0000000..be9d844 --- /dev/null +++ b/pack.sh @@ -0,0 +1,7 @@ +./sstrip $1 +#cp gz-stub intro +#gzip -c9 $1 >> intro +7z a -tGZIP -mx=9 -mfb=64 intro.gz $1 +cat gz-stub intro.gz > intro +chmod +x intro +ls -l intro diff --git a/play.c b/play.c new file mode 100644 index 0000000..d5a0d9b --- /dev/null +++ b/play.c @@ -0,0 +1,229 @@ +#include "SDL.h" +#include "dl_init.h" +#include "synth.h" +#include "play.h" +#include "song.h" + +#define msin(x) __builtin_sinf(x) +#define mcos(x) __builtin_cosf(x) +#define mfmodf(x,y) fn.fmodf(x,y) + +#ifdef OUTFILE +#include +FILE *fout; +#endif + +#define NUM_VOICES 64 + +Voice voices[NUM_RHYTHM_CHANNELS+NUM_VOICES]={{0}}; +float mix_buf[BUFFER_SIZE]={0}; +unsigned int last_voice_used=0; +int buf_start; + +float current_time=0; +int rhythm_offset; +float global_vol=1.0f; +int music_ticks=-1; + + +float cam_rotation, cam_rotation0, cam_rot_x, cam_rot_y, cam_rot_z; +float tri_z_spread=8.0f; + +int negative_bars=0; + +enum params{ + FOV=0, + TRI_Z_SPREAD, + TRI_SPEED, + CAMERA_POS, + NEGATIVE, + NUM_PARAMS, +}; + +typedef struct +{ + float x, y, z, w, x1, y1, z1, w1, x0, y0, z0, w0, scale, offset, trans_start, trans_end; +} Param; + + +Param params[NUM_PARAMS]; + +extern void update_params(); + +void change_param(int which) +{ + if (which < 0) + which = rand_4k()%NUM_PARAMS; + params[which].x0 = params[which].x; + params[which].y0 = params[which].y; + params[which].z0 = params[which].z; + params[which].x1 = sfrand() * params[which].scale + params[which].offset; + params[which].y1 = sfrand() * params[which].scale + params[which].offset; + params[which].z1 = sfrand() * params[which].scale + params[which].offset; + params[which].trans_start = current_time; + params[which].trans_end = current_time + sfrand()*2.0f+2.0f; // entre 1 y 5 +} + + +static void note_on(int note, float vol, int instrument) +{ + if (rand()%10) + { + int j = last_voice_used + NUM_RHYTHM_CHANNELS; + last_voice_used = (last_voice_used + 1) % NUM_VOICES; + voices[j].pitch = 440.0f*detune(note-45,0); + voices[j].pos = buf_start; + voices[j].ins = instrument; + voices[j].vol = global_vol*0.19921875f*vol; + voices[j].active = 1; + } +} + +enum chords_enum { + MAJOR=0, + MINOR, + MAJOR_SEVENTH, + MINOR_SEVENTH, + NUM_CHORDS, +}; + +enum scales_enum { + MAJOR_SCALE=0, + MINOR_SCALE, + NUM_SCALES, +}; + +int chords[4*NUM_CHORDS] = { + 0,4,7,-1, + 0,3,7,-1, + 0,4,7,11, + 0,3,7,11, +}; + +int scales[7*NUM_SCALES] = { + 0,2,4,5,7,9,11, + 0,2,3,5,7,8,10, +}; + +static void chord_on(int base, int type, float vol, int instrument) +{ + note_on(base+chords[4*type], vol, instrument); + note_on(base+chords[4*type+1], vol, instrument); + note_on(base+chords[4*type+2], vol, instrument); + if (chords[4*type+3] >= 0) + note_on(base+chords[4*type+3], vol, instrument); +} + +int current_chord_base, current_chord_type; +int bass_arpeggio[3]={0,1,2}; + +// Main audio callback +static void play(Song *s, Uint8 *stream, int len) +{ + unsigned int i; + unsigned int num_samples=len>>1; + float tmp; + Sint16 *buf=(Sint16 *)stream; + + current_time += num_samples/SAMPLE_RATE; + +#ifdef X86_ASM + __asm__("rep; stosl;"::"a"(0), "c"(BUFFER_SIZE), "D"(mix_buf)); +#else + __builtin_memset(mix_buf, 0, BUFFER_SIZE*sizeof(float)); +#endif + + + if ((current_time - music_ticks * ROW_DURATION) > ROW_DURATION ) + { + ++music_ticks; + buf_start = ((current_time - music_ticks * ROW_DURATION)*SAMPLE_RATE)-num_samples; + + + // Cambio de acorde cada 4 compases + if (music_ticks%32 == 0) + { + current_chord_base=rand()%12+16; + current_chord_type=rand()%2; + change_param(-1); + } + + if (music_ticks%8 == 0) + { + int i1=rand()%3; + int i2=rand()%3; + int tmp = bass_arpeggio[i1]; + bass_arpeggio[i1] = bass_arpeggio[i2]; + bass_arpeggio[i2] = tmp; + + if (--negative_bars < 0) + { + negative_bars = rand_4k()%32+8; + params[NEGATIVE].x0 = params[NEGATIVE].x1; + if (params[NEGATIVE].x1 == 0.0f) + params[NEGATIVE].x1=1.0f; + else + params[NEGATIVE].x1=0.0f; + params[NEGATIVE].trans_start = current_time; + params[NEGATIVE].trans_end = current_time + 2.0f; // entre 1 y 5 + } + } + + if (music_ticks%16 == 0) + chord_on(current_chord_base, current_chord_type, 0.2f, 1); + + if (music_ticks%2 == 0) + { + float vol = 1.0f-((music_ticks%8)/8.0f); + chord_on(current_chord_base, current_chord_type, vol, 3); + + } + + if (music_ticks%2 == 0) + { + note_on(current_chord_base+12+chords[4*current_chord_type+rand()%3], 1.0f, 4); + note_on(current_chord_base-12+chords[4*current_chord_type+bass_arpeggio[(music_ticks%6)/2]], 1.0f,2); + } + else + { + if (rand() % 2 == 0) + note_on(current_chord_base+12+scales[4*current_chord_type%2+rand()%7], 0.5f, 4); + + if (rand() % 4 == 0) + note_on(current_chord_base-12+scales[4*current_chord_type%2+(music_ticks%6)], 0.5f,2); + } + } + + // Ahora vamos sintetizando las voces + for (i=0; i < NUM_VOICES + NUM_RHYTHM_CHANNELS; ++i) + { + if (voices[i].active) + { + voices[i].active=synth(&voices[i], num_samples, mix_buf); + } + } + + // convertimos a Sint16 + for (i=0; i1.0f) tmp=1.0f; + else if(tmp<-1.0f) tmp=-1.0f; + buf[i]=(Sint16)(tmp*32640.0f); + } + +#ifdef OUTFILE + fwrite(buf, sizeof(Sint16), num_samples, fout); +#endif + +} + +SDL_AudioSpec desired={44100, + AUDIO_S16SYS, + 1, + 0, + BUFFER_SIZE, + 0, + 0, + (void (*)(void *, Uint8 *, int)) play, + 0}; diff --git a/play.h b/play.h new file mode 100644 index 0000000..60c5eff --- /dev/null +++ b/play.h @@ -0,0 +1,27 @@ +#ifndef _TRACK_H_ +#define _TRACK_H_ + +#include "SDL.h" +#include "synth.h" + +#define NUM_PATTERNS 300 +#define NUM_ENVELOPES 4 +#define NUM_INSTRUMENTS 300 +#define NUM_RHYTHM_CHANNELS 10 +#define NUM_CHANNELS 50 +#define TRACK_LENGTH 16 + +//#define OUTFILE "salida.raw" + +typedef struct _Song +{ + //float row_duration; // in seconds + Envelope envelopes[NUM_ENVELOPES]; + Instrument insts[NUM_INSTRUMENTS]; +} Song; + +#define sfrand() (2.0f*whitenoise()-1.0f) + +#endif + + diff --git a/song.h b/song.h new file mode 100644 index 0000000..c19021e --- /dev/null +++ b/song.h @@ -0,0 +1,80 @@ +#ifndef SONG_H +#define SONG_H + +#define ROW_DURATION 0.27 + +Song song={ + //Envelopes + { + {0,0,0,0,0}, // env nr 0 = special case (no envelope) + {20,120,40,200,20}, + {0,5,30,30,0}, + {0,20,15,30,0}, + }, + // Instruments + { + // Ins 0 (bass drum) + { + 0.0f, // cutoff + 0.0f, // lfo_amp + 0, // lfo_freq + 0, // res + 0,0, + 0,0, // detune + 0,0, + 0, + 0, 0, + }, + // Ins 1 (hihat) + { + -4000.0f, + 500.0f, + 5, + 100, + 24,1, + 36,-1, + 70,80, + 0, + 1,0, + }, + // Ins 2 (bass) + { + 700.0f, // cutoff + -400.0f, // lfo_amp + -1, // lfo_freq + 15, // res + 12,1, + 12,0, // detune + 70,70, // vols + 10, //noise + 2, 0, + }, + // Ins 3 ("sin" con attack) + { + 800.0f, // cutoff + 300.0f, // lfo_amp + 2, // lfo_freq + 30, // res + 12,1, + 12,0, // detune + 40,60, // vols + 0, //noise + 3, 0, + }, + // Ins 4 (lead) + { + 1848.0f, // cutoff + 500.0f, // lfo_amp + 80, // lfo_freq + 15, // res + 24,1, + 12,0, // detune + 40,50, // vols + 0, //noise + 2, 0, + }, + }, +}; + +#endif + diff --git a/sstrip b/sstrip new file mode 100755 index 0000000000000000000000000000000000000000..d51aabe07c5694d4b1cda9e9abe693a8ebdad888 GIT binary patch literal 15916 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 literal 0 HcmV?d00001 diff --git a/sstrip.c b/sstrip.c new file mode 100644 index 0000000..60128e6 --- /dev/null +++ b/sstrip.c @@ -0,0 +1,332 @@ + +/* sstrip, version 2.0: Copyright (C) 1999-2001 by Brian Raiter, under the + * GNU General Public License. No warranty. See LICENSE for details. + */ + +/* #include "config_xor.h" */ + +#include +#include +#include +#include +#include +#include + +#if !defined(__ia64) && !defined(__ia64__) && !defined(__itanium__) && \ + !defined(__alpha) && !defined(__alpha__) && \ + (defined(__linux__) || defined(__FreeBSD__)) && \ + (defined(__i386__) || defined(__i386) || defined(i386)) + +/* || defined(__sun) || defined(__sun__) || defined(sun) */ + +#if defined(__linux__) +#include +#else +#include +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#if ELF_CLASS == ELFCLASS32 +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Phdr Elf32_Phdr +#else +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Phdr Elf64_Phdr +#endif + +/* The name of the program. + */ +static char const *progname; + +/* The name of the current file. + */ +static char const *filename; + + +/* A simple error-handling function. FALSE is always returned for the + * convenience of the caller. + */ +static int err(char const *errmsg) +{ + fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg); + return FALSE; +} + +/* A macro for I/O errors: The given error message is used only when + * errno is not set. + */ +#define ferr(msg) (err(errno ? strerror(errno) : (msg))) + +/* readelfheader() reads the ELF header into our global variable, and + * checks to make sure that this is in fact a file that we should be + * munging. + */ +static int readelfheader(int fd, Elf_Ehdr *ehdr) +{ + errno = 0; + if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) + return ferr("missing or incomplete ELF header."); + + /* Check the ELF signature. + */ + if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 && + ehdr->e_ident[EI_MAG1] == ELFMAG1 && + ehdr->e_ident[EI_MAG2] == ELFMAG2 && + ehdr->e_ident[EI_MAG3] == ELFMAG3)) + return err("missing ELF signature."); + + /* Compare the file's class and endianness with the program's. + */ + if (ehdr->e_ident[EI_DATA] != ELF_DATA) + return err("ELF file has different endianness."); + if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) + return err("ELF file has different word size."); + + /* Check the target architecture. + */ + if (ehdr->e_machine != ELF_ARCH) + return err("ELF file created for different architecture."); + + /* Verify the sizes of the ELF header and the program segment + * header table entries. + */ + if (ehdr->e_ehsize != sizeof(Elf_Ehdr)) + return err("unrecognized ELF header size."); + if (ehdr->e_phentsize != sizeof(Elf_Phdr)) + return err("unrecognized program segment header size."); + + /* Finally, check the file type. + */ + if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) + return err("not an executable or shared-object library."); + + return TRUE; +} + +/* readphdrtable() loads the program segment header table into memory. + */ +static int readphdrtable(int fd, Elf_Ehdr const *ehdr, Elf_Phdr **phdrs) +{ + size_t size; + + if (!ehdr->e_phoff || !ehdr->e_phnum) + return err("ELF file has no program header table."); + + size = ehdr->e_phnum * sizeof **phdrs; + if (!(*phdrs = malloc(size))) + return err("Out of memory!"); + + errno = 0; + if (read(fd, *phdrs, size) != (ssize_t)size) + return ferr("missing or incomplete program segment header table."); + + return TRUE; +} + +/* getmemorysize() determines the offset of the last byte of the file + * that is referenced by an entry in the program segment header table. + * (Anything in the file after that point is not used when the program + * is executing, and thus can be safely discarded.) + */ +static int getmemorysize(Elf_Ehdr const *ehdr, Elf_Phdr const *phdrs, + unsigned long *newsize) +{ + Elf_Phdr const *phdr; + unsigned long size, n; + int i; + + /* Start by setting the size to include the ELF header and the + * complete program segment header table. + */ + size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs; + if (size < sizeof *ehdr) + size = sizeof *ehdr; + + /* Then keep extending the size to include whatever data the + * program segment header table references. + */ + for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { + if (phdr->p_type != PT_NULL) { + n = phdr->p_offset + phdr->p_filesz; + if (n > size) + size = n; + } + } + + *newsize = size; + return TRUE; +} + +/* truncatezeros() examines the bytes at the end of the file's + * size-to-be, and reduces the size to exclude any trailing zero + * bytes. + */ +static int truncatezeros(int fd, unsigned long *newsize) +{ + unsigned char contents[1024]; + unsigned long size, n; + + size = *newsize; + do { + n = sizeof contents; + if (n > size) + n = size; + if (lseek(fd, size - n, SEEK_SET) == (off_t)-1) + return ferr("cannot seek in file."); + if (read(fd, contents, n) != (ssize_t)n) + return ferr("cannot read file contents"); + while (n && !contents[--n]) + --size; + } while (size && !n); + + /* Sanity check. + */ + if (!size) + return err("ELF file is completely blank!"); + + *newsize = size; + return TRUE; +} + +/* modifyheaders() removes references to the section header table if + * it was stripped, and reduces program header table entries that + * included truncated bytes at the end of the file. + */ +static int modifyheaders(Elf_Ehdr *ehdr, Elf_Phdr *phdrs, + unsigned long newsize) +{ + Elf_Phdr *phdr; + int i; + + /* If the section header table is gone, then remove all references + * to it in the ELF header. + */ + if (ehdr->e_shoff >= newsize) { + ehdr->e_shoff = 0; + ehdr->e_shnum = 0; + ehdr->e_shentsize = 0; + ehdr->e_shstrndx = 0; + } + + /* The program adjusts the file size of any segment that was + * truncated. The case of a segment being completely stripped out + * is handled separately. + */ + for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { + if (phdr->p_offset >= newsize) { + phdr->p_offset = newsize; + phdr->p_filesz = 0; + } else if (phdr->p_offset + phdr->p_filesz > newsize) { + phdr->p_filesz = newsize - phdr->p_offset; + } + } + + return TRUE; +} + +/* commitchanges() writes the new headers back to the original file + * and sets the file to its new size. + */ +static int commitchanges(int fd, Elf_Ehdr const *ehdr, Elf_Phdr *phdrs, + unsigned long newsize) +{ + size_t n; + + /* Save the changes to the ELF header, if any. + */ + if (lseek(fd, 0, SEEK_SET)) + return ferr("could not rewind file"); + errno = 0; + if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) + return err("could not modify file"); + + /* Save the changes to the program segment header table, if any. + */ + if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) { + err("could not seek in file."); + goto warning; + } + n = ehdr->e_phnum * sizeof *phdrs; + if (write(fd, phdrs, n) != (ssize_t)n) { + err("could not write to file"); + goto warning; + } + + /* Eleventh-hour sanity check: don't truncate before the end of + * the program segment header table. + */ + if (newsize < ehdr->e_phoff + n) + newsize = ehdr->e_phoff + n; + + /* Chop off the end of the file. + */ + if (ftruncate(fd, newsize)) { + err("could not resize file"); + goto warning; + } + + return TRUE; + + warning: + return err("ELF file may have been corrupted!"); +} + +/* main() loops over the cmdline arguments, leaving all the real work + * to the other functions. + */ +int main(int argc, char *argv[]) +{ + int fd; + Elf_Ehdr ehdr; + Elf_Phdr *phdrs; + unsigned long newsize; + char **arg; + int failures = 0; + + if (argc < 2 || argv[1][0] == '-') { + printf("Usage: sstrip FILE...\n" + "sstrip discards all nonessential bytes from an executable.\n\n" + "Version 2.0 Copyright (C) 2000,2001 Brian Raiter.\n" + "This program is free software, licensed under the GNU\n" + "General Public License. There is absolutely no warranty.\n"); + return EXIT_SUCCESS; + } + + progname = argv[0]; + + for (arg = argv + 1 ; *arg != NULL ; ++arg) { + filename = *arg; + + fd = open(*arg, O_RDWR); + if (fd < 0) { + ferr("can't open"); + ++failures; + continue; + } + + if (!(readelfheader(fd, &ehdr) && + readphdrtable(fd, &ehdr, &phdrs) && + getmemorysize(&ehdr, phdrs, &newsize) && + truncatezeros(fd, &newsize) && + modifyheaders(&ehdr, phdrs, newsize) && + commitchanges(fd, &ehdr, phdrs, newsize))) + ++failures; + + close(fd); + } + + return failures ? EXIT_FAILURE : EXIT_SUCCESS; +} + +#else + +int main() +{ + return (EXIT_SUCCESS); +} + +#endif diff --git a/synth.c b/synth.c new file mode 100644 index 0000000..679ca94 --- /dev/null +++ b/synth.c @@ -0,0 +1,183 @@ +#include "synth.h" +#include "play.h" +#include "dl_init.h" +#include + +#define msin(x) __builtin_sinf(x) +#define mcos(x) __builtin_cosf(x) +#define mfmodf(x,y) fn.fmodf(x,y) + +extern float current_time; +extern Song song; + +float mtan(float x) +{ + float sin_x, cos_x; + #ifdef X86_ASM + __asm__("fsincos" : "=t" (cos_x), "=u" (sin_x) : "0" (x)); + #else + sin_x=msin(x); + cos_x=mcos(x); + #endif + + return sin_x/cos_x; +} + +//#define SYNTH_HACKS + +// Evaluates the envelope e at position pos +// Lineal interpolation +float getADSR(Envelope *e, float pos) +{ + float p=pos*100.0f; + float A=e->A; + if (p < 0) + return 9.96589660645e-05f; + if (p < A) + return (p/A)+9.96589660645e-05f; + + p -= A; + + float D=e->D; + float S=e->S*0.00994873046875f; + if (p <= D) + return (1.0f-(p * (1.0f - S)) / D); + + p -= D; + + float sustain_time=e->sustain_time; + if (p <= sustain_time) + return S; + + p -= sustain_time; + + float R=e->R; +#ifndef SYNTH_HACKS + if (p < R) + return S - S * (p/R); + return 0.0f; +#else + return S - S * (p/R); +#endif +} + +float detune(int coarse, int fine) +{ + return fn.powf(2.0f, (coarse+(fine/100.0f))/12.0f); +} + + +int synth(Voice *v, int len, float *mix_buf) +{ + Instrument *ins=&song.insts[v->ins]; + //float pitch_sine = v->pitch * ins->sine_detune; + float pitch_square= v->pitch * detune(ins->square_detune_coarse, ins->square_detune_fine); + float pitch_saw = v->pitch * detune(ins->saw_detune_coarse, ins->saw_detune_fine); + float pitch_env, vol, res, t; + int i; + + for (i=0; ipos+i)*invSAMPLE_RATE; + v->cur_vol = vol = getADSR(&song.envelopes[ins->vol_envelope], t); + if(ins->pitch_envelope) + pitch_env = getADSR(&song.envelopes[ins->pitch_envelope], t); + else + pitch_env = 1.0f; + + // Calc. and mix the oscillators + // Noise + res = 0.00994873046875f*ins->noise_vol*(2.0f*whitenoise()-1.0f) ; + + // Sine + //res += ins->sine_vol * msin(DOSPI*pitch_sine*pitch_env*t); + + + // Square + + float sqvol=ins->square_vol*0.00994873046875f; + if (mfmodf(t, 1.0f/(pitch_square*pitch_env)) > (0.5f/(pitch_square*pitch_env))) + res += sqvol; + else + res -= sqvol; + + + // Sine + //float sqvol=ins->square_vol*0.00994873046875f; + //res += sqvol * msin(DOSPI*pitch_square*pitch_env*t); + + + + // Saw + res += 0.00994873046875f*ins->saw_vol * 2.0f*__builtin_fabsf((mfmodf(t*pitch_saw*pitch_env, 2.0f) - 1.0f))-1.0f; + + + // Apply the ADSR + res *= vol; + + // Calculamos el valor del cutoff aplicando LFO + // TODO: Comprobar si vale la pena eliminar este if + float cutoff, lfo_freq; + if (ins->lfo_freq < 0) + { + lfo_freq=-ins->lfo_freq; + t=current_time; + } + else + { + lfo_freq=ins->lfo_freq; + } + lfo_freq *= 0.099609375f; + cutoff= ins->cutoff + ins->lfo_amp * mcos(DOSPI * lfo_freq * t); + + // TODO: Cambiar el factor de la resonancia para + // ajustar el rango a valores mas utiles. + // ahora mismo va de 0.0 a 2.55 con incrementos de 0.01 y + // no parece que > 1.5 sea util + t = ins->resonance*0.00994873046875f; + + // Filter coefficients + float c, c2,a1,a2,b1,b2; + + // This is common to high-pass and low-pass + float param_tan = PI_samplerate * cutoff; + + if (cutoff > 0.0f) // Low-pass + { + c=1.0f / mtan(param_tan); + c2 = c*c; + + a1 = 1.0f / ( 1.0f + t*c + c2); + a2 = 2.0f * a1; + b1 = 2.0f * ( 1.0f - c2) * a1; + } + + else // High-pass + { + c = mtan(-param_tan); + c2 = c*c; + + a1 = 1.0f / ( 1.0f + t*c + c2); + a2 = -2.0f * a1; + b1 = 2.0f * ( c2 - 1.0f) * a1; + } + + b2 = ( 1.0f - t*c + c2) * a1; + + v->yn[0] = a1*res + a2*v->xn[1] + a1*v->xn[2] - + b1*v->yn[1] - b2*v->yn[2]; + + v->xn[2]=v->xn[1]; + v->xn[1]=res; + v->yn[2]=v->yn[1]; + v->yn[1]=v->yn[0]; + + mix_buf[i] += v->yn[0] * v->vol; + } + + v->pos+=len; + + if (vol > 0.0f) + return 1; + return 0; +} diff --git a/synth.h b/synth.h new file mode 100644 index 0000000..a39a67d --- /dev/null +++ b/synth.h @@ -0,0 +1,74 @@ +#ifndef _SYNTH_H_ +#define _SYNTH_H_ + + +#define BUFFER_SIZE 1024 +#define SAMPLE_RATE 44032.0f +#define invSAMPLE_RATE 2.26497650146e-05f + +#define FLOAT2INTCAST(x) (*((int*)(&x))) +#define FLOAT2UINTCAST(x) (*((unsigned int*)(&x))) + +#define PI_X 0x40490FDB +#define DOSPI_X 0x40C90FDB +#define PI_2_X 0x3FC90FDB + +#define PI 3.140625f +#define PI_samplerate 7.10487365723e-05f +#define DOSPI 6.28125f +#define DOSPI_samplerate 0.000142097473145f + +typedef unsigned char U8; +typedef signed char S8; + +typedef struct _Envelope +{ + U8 A, D, S, R; // In 1/100ths of a second except S which is vol*100 + U8 sustain_time; // In 1/100ths of a second +} Envelope; + +typedef struct _Instrument +{ + // Filter + float cutoff; // >0 LP; <0 HP + float lfo_amp; + S8 lfo_freq; + U8 resonance; // in 1/100ths + + S8 square_detune_coarse; // in tones + S8 square_detune_fine; // in cents + S8 saw_detune_coarse; + S8 saw_detune_fine; + + U8 square_vol; + U8 saw_vol; + U8 noise_vol; + + U8 vol_envelope; + U8 pitch_envelope; + +} Instrument; + + +typedef struct _Voice +{ + float pitch; + float vol; + float cur_vol; + + float xn[3]; + float yn[3]; + + int pos; // position in samples since the start + U8 ins; + U8 active; // { 0 ==> inactiva, (not 0) ==> activa } + + +} Voice; + +extern int synth(Voice *c, int len, float *mix_buf); +#define whitenoise() (fn.rand()/(float)RAND_MAX) +#define rand_4k() (fn.rand()) +//extern float whitenoise(); +extern float detune(int coarse, int fine); +#endif -- 2.34.1