Browse Source

Initial commit

dirkson 2 months ago
parent
commit
b24d9deecf
5 changed files with 1040 additions and 11 deletions
  1. 15
    11
      LICENSE
  2. 274
    0
      build
  3. 119
    0
      include/sfxr.h
  4. 16
    0
      meson.build
  5. 616
    0
      src/sfxr.c

+ 15
- 11
LICENSE View File

@@ -1,21 +1,25 @@
1 1
 MIT License
2 2
 
3
-Copyright (c) <year> <copyright holders>
3
+Björn cleaned up DrPetter's original code, I pulled that code out and made a standalone C library out of it.
4
+
5
+Copyright (c) 2018 Dirkson
6
+Copyright (c) 2017 Björn Ritzl
7
+Copyright (c) 2007 DrPetter
4 8
 
5 9
 Permission is hereby granted, free of charge, to any person obtaining a copy
6 10
 of this software and associated documentation files (the "Software"), to deal
7 11
 in the Software without restriction, including without limitation the rights
8 12
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
-copies of the Software, and to permit persons to whom the Software is furnished
10
-to do so, subject to the following conditions:
13
+copies of the Software, and to permit persons to whom the Software is
14
+furnished to do so, subject to the following conditions:
11 15
 
12
-The above copyright notice and this permission notice (including the next
13
-paragraph) shall be included in all copies or substantial portions of the
14
-Software.
16
+The above copyright notice and this permission notice shall be included in all
17
+copies or substantial portions of the Software.
15 18
 
16 19
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
19
-OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+SOFTWARE.

+ 274
- 0
build View File

@@ -0,0 +1,274 @@
1
+#!/bin/bash
2
+
3
+#************
4
+#***CONFIG***
5
+#************
6
+
7
+#If COMPILER isn't set, the script will attempt to figure it out itself.
8
+#If you change the compiler, you'll need to clean your build.
9
+#COMPILER=musl-gcc
10
+
11
+#If this isn't set, the script will attempt to find ninja and samu, in that order.
12
+#Alternatives include samurai's "samu"
13
+#NINJACOMMAND=ninja
14
+
15
+#Directories
16
+BUILDDIR=meson
17
+DOCDIR=doc
18
+BINDIR=bin
19
+LIBDIR=lib
20
+DEPDIR=subprojects
21
+SCRIPTDIR=scripts
22
+
23
+#***********
24
+#***OSMIA***
25
+#***********
26
+#
27
+# This is osmia, a build script for meson.
28
+#
29
+# Official URL:
30
+# https://git.orangehattech.com/dirkson/osmia
31
+#
32
+
33
+#*************
34
+#***LICENSE***
35
+#*************
36
+#
37
+# MIT License
38
+#
39
+# Copyright (c) 2018 Dirkson
40
+#
41
+# Permission is hereby granted, free of charge, to any person obtaining a copy
42
+# of this software and associated documentation files (the "Software"), to deal
43
+# in the Software without restriction, including without limitation the rights
44
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+# copies of the Software, and to permit persons to whom the Software is
46
+# furnished to do so, subject to the following conditions:
47
+#
48
+# The above copyright notice and this permission notice shall be included in all
49
+# copies or substantial portions of the Software.
50
+#
51
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
57
+# SOFTWARE.
58
+#
59
+
60
+#Functions
61
+
62
+osmia_help () {
63
+	echo "Osmia build script for meson."
64
+	echo "Usage: ./build [-mode] [target]"
65
+	echo "Target will be passed to ninja directly"
66
+	echo "Mode defaults to release, or is one of the following:"
67
+	echo "-r   OR --release    : Builds using Meson's release mode"
68
+	echo "-d   OR --debug      : Builds using Meson's debug mode, with --werror added"
69
+	echo "-c   OR --clean      : Cleans up current project meson/ninja/osmia files"
70
+	echo "-fc  OR --full-clean : Fully clean - Removes dependencies too"
71
+	echo "-a   OR --add-san    : Clang's address sanitizer"
72
+	echo "-w   OR --win        : Cross-compile for win32 using scripts/win32cross.txt"
73
+	echo "-w64 OR --win64      : cross-compile for win64"
74
+	echo "-o   OR --osx        : cross-compile for OSX"
75
+}
76
+osmia_clean () {
77
+	rm -rf $BUILDDIR $BINDIR $LIBDIR
78
+}
79
+
80
+osmia_symlink () {
81
+	FILES="$(find $1 -maxdepth 1 -type f $2 2> /dev/null)"
82
+	if [ ! -z "$FILES" ]; then
83
+		mkdir -p $3 2> /dev/null
84
+		rm -rf $3/* 2> /dev/null
85
+		for I in $FILES; do
86
+			ln -s ../$I $3/
87
+		done
88
+	fi
89
+}
90
+
91
+osmia_get () {
92
+	if [ ! -d "$1" ]; then
93
+		$2
94
+		if [ ! $? -eq 0 ]; then
95
+			echo "osmia: git command failed: $1"
96
+			exit 1
97
+		fi
98
+		if [ ! -d "$1" ]; then
99
+			echo "osmia: could not find directory: $1"
100
+			exit 1
101
+		fi
102
+	fi
103
+}
104
+
105
+
106
+
107
+clear
108
+
109
+err=0;
110
+
111
+if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
112
+	err=1
113
+	echo "osmia: er... Yeah, don't source this file."
114
+	return 1
115
+fi
116
+
117
+#What type of build?
118
+case "$1" in
119
+-d|-debug|--debug)
120
+	DIR=debug
121
+	BLD=debug
122
+	MESONOPTS="--werror"
123
+;;
124
+-a)
125
+	DIR=debug
126
+	BLD=debug
127
+	MESONOPTS=-Db_sanitize=address
128
+	MESONOPTS="--werror"
129
+;;
130
+-w|-win|--win|-window|--windows)
131
+	DIR=release
132
+	BLD=release
133
+	MESONOPTS="--cross-file scripts/win32cross.txt"
134
+;;
135
+-w64|-win64|--win64|-windows64|--windows64)
136
+	DIR=release
137
+	BLD=release
138
+	MESONOPTS="--cross-file scripts/win64cross.txt"
139
+;;
140
+-c|-clean|--clean)
141
+	if [ "$#" -ne 1 ]; then
142
+		echo "osmia: you passed additional arguments to clean. I have no idea what you want. Did not clean."
143
+		exit 1
144
+	fi
145
+	osmia_clean
146
+	echo "osmia: cleaned."
147
+	exit 0
148
+;;
149
+-fc|-fullclean|--fullclean|-full-clean|--full-clean)
150
+	if [ "$#" -ne 1 ]; then
151
+		echo "osmia: you passed additional arguments to clean. I have no idea what you want. Did not clean."
152
+		exit 1
153
+	fi
154
+	osmia_clean
155
+	rm -rf $DEPDIR
156
+	echo "osmia: fully cleaned."
157
+	exit 0
158
+;;
159
+-?|-h|-help|--help)
160
+	osmia_help
161
+	err=1
162
+;;
163
+-r|--release|*)
164
+	DIR=release
165
+	BLD=release
166
+;;
167
+esac
168
+
169
+#do some basic error checking for the user
170
+if [ -z "$NINJACOMMAND" ]; then
171
+	NINJACOMMAND=ninja
172
+	if [ ! -x "$(command -v $NINJACOMMAND)" ]; then
173
+		NINJACOMMAND=samu
174
+		if [ ! -x "$(command -v $NINJACOMMAND)" ]; then
175
+			echo "osmia: neither ninja nor samu are installed. One of the two is required to build."
176
+			echo "osmia: Please install either samurai's samu or ninja-build's ninja."
177
+			err=1;
178
+		fi
179
+	fi
180
+else
181
+	if [ ! -x "$(command -v $NINJACOMMAND)" ]; then
182
+		echo "osmia: manually specified ninja command not found"
183
+		err=1;
184
+	fi
185
+fi
186
+if [ ! -x "$(command -v meson)" ]; then
187
+	echo "osmia: meson not installed. The meson build system is required to build, please install.";
188
+	err=1;
189
+fi
190
+if [ -z "$COMPILER" ]; then
191
+	if [ -x "$(command -v clang)" ]; then
192
+		COMPILER="clang"
193
+	elif [ -x "$(command -v musl-gcc)" ]; then
194
+		COMPILER="musl-gcc -static"
195
+	elif [ -x "$(command -v gcc)" ]; then
196
+		COMPILER="gcc"
197
+	elif [ -x "$(command -v tcc)" ]; then
198
+		COMPILER="tcc"
199
+	elif [ -x "$(command -v icc)" ]; then
200
+		COMPILER="icc"
201
+	else
202
+		echo "osmia: unable to find any compiler at all. Please install one: clang, musl-gcc, gcc, tcc, icc"
203
+		err=1
204
+	fi
205
+else
206
+	if [ ! -x "$(command -v $COMPILER)" ]; then
207
+		echo "osmia: manually specified compiler does not exist. Failing."
208
+		err=1
209
+	fi
210
+fi
211
+if [ ! -x "$(command -v ccache)" ]; then
212
+	echo "somia: ccache not installed. Installing it could speed the build up. Hint Hint.";
213
+fi
214
+
215
+if [ "$#" -gt 2 ]; then
216
+	osmia_help
217
+	echo "osmia: failed, too many parameters."
218
+	err=1;
219
+fi
220
+
221
+#Note: For exit '0' is 'true' and '1' in 'false', in spite of all logic.
222
+if [ $err -ne 0 ]; then
223
+	exit 1
224
+fi
225
+
226
+#Grab dependencies
227
+if [ -d "$SCRIPTDIR" ] && [ -e scripts/dependencies ]; then
228
+	mkdir -p $DEPDIR 2> /dev/null
229
+	cd "$DEPDIR"
230
+	source ../scripts/dependencies
231
+	cd ../
232
+fi
233
+
234
+
235
+#Set up basic directory structure, if needed
236
+mkdir -p $BUILDDIR 2> /dev/null
237
+
238
+#MESONOPTS=MESONOPTS:"-Dc_args=$3"
239
+
240
+if [ ! -d "$BUILDDIR/$DIR" ]; then
241
+	export CC="$COMPILER"
242
+	#Run meson if required
243
+	mkdir $BUILDDIR/$DIR
244
+	meson $BUILDDIR/$DIR $MESONOPTS --buildtype $BLD
245
+	if [ ! $? -eq 0 ]; then
246
+		#Generally an error here means we need to clean before the next run
247
+		tail $BUILDDIR/$DIR/meson-logs/meson-log.txt
248
+		cp $BUILDDIR/$DIR/meson-logs/meson-log.txt meson-log.txt
249
+		echo "osmia: meson returned an error. Please check meson-log.txt for more info."
250
+		osmia_clean
251
+		exit 1
252
+	fi
253
+#else
254
+#May wish to look into this in the future
255
+#meson configure $MESONOPTS
256
+fi
257
+
258
+#Actually build
259
+cd $BUILDDIR/$DIR
260
+$NINJACOMMAND $2
261
+if [ ! $? -eq 0 ]; then
262
+	cd ../../
263
+	exit 1
264
+fi
265
+cd ../../
266
+
267
+#set up symlinks
268
+osmia_symlink "$BUILDDIR/$DIR/*" "-name *.a -o -name *.so -o -name *.dll" $LIBDIR
269
+osmia_symlink "$BUILDDIR/$DIR/*" "-not -name *.so -not -name *.dll -executable -not -name sanitycheckc.exe" $BINDIR
270
+osmia_symlink "$BUILDDIR/$DIR/*" "-name *.html -o -name *.htm" $DOCDIR
271
+
272
+echo "osmia: successful build."
273
+
274
+exit 0

+ 119
- 0
include/sfxr.h View File

@@ -0,0 +1,119 @@
1
+#pragma once
2
+#ifndef SFXR_H
3
+#define SFXR_H
4
+
5
+#ifdef __cplusplus
6
+extern "C"{
7
+#endif
8
+
9
+#define rnd(n) (rand()%(n+1))
10
+
11
+#define PI 3.14159265f
12
+
13
+struct SfxrSound {
14
+	unsigned char* data;
15
+	int length;
16
+};
17
+
18
+typedef struct Sfxr {
19
+	int wave_type;
20
+
21
+	float p_base_freq;
22
+	float p_freq_limit;
23
+	float p_freq_ramp;
24
+	float p_freq_dramp;
25
+	float p_duty;
26
+	float p_duty_ramp;
27
+
28
+	float p_vib_strength;
29
+	float p_vib_speed;
30
+	float p_vib_delay;
31
+
32
+	float p_env_attack;
33
+	float p_env_sustain;
34
+	float p_env_decay;
35
+	float p_env_punch;
36
+
37
+	int filter_on;
38
+	float p_lpf_resonance;
39
+	float p_lpf_freq;
40
+	float p_lpf_ramp;
41
+	float p_hpf_freq;
42
+	float p_hpf_ramp;
43
+
44
+	float p_pha_offset;
45
+	float p_pha_ramp;
46
+
47
+	float p_repeat_speed;
48
+
49
+	float p_arp_speed;
50
+	float p_arp_mod;
51
+
52
+	float master_vol;
53
+	float sound_vol;
54
+
55
+	float vib_phase;
56
+	float vib_speed;
57
+	float vib_amp;
58
+
59
+	int env_stage;
60
+	int env_time;
61
+	int env_length[3];
62
+	float env_vol;
63
+
64
+	int iphase;
65
+	float phaser_buffer[1024];
66
+	int ipp;
67
+	float noise_buffer[32];
68
+
69
+	float square_duty;
70
+	float square_slide;
71
+
72
+	int rep_time;
73
+	int rep_limit;
74
+	int arp_time;
75
+	int arp_limit;
76
+	double arp_mod;
77
+
78
+	double fslide;
79
+	double fdslide;
80
+
81
+	float fphase;
82
+	float fdphase;
83
+
84
+	float fltp;
85
+	float fltdp;
86
+	float fltdmp;
87
+	float fltphp;
88
+	float flthp;
89
+	float flthp_d;
90
+	float fltw;
91
+	float fltw_d;
92
+
93
+	int period;
94
+	int phase;
95
+
96
+	double fperiod;
97
+	double fmaxperiod;
98
+
99
+	int playing_sample;
100
+	int samples_played;
101
+
102
+	int buffer_byteswritten;
103
+	int file_bytesswritten;
104
+	float filesample;
105
+} Sfxr;
106
+
107
+struct SfxrSound SfxrBlip(int seed);
108
+struct SfxrSound SfxrJump(int seed);
109
+struct SfxrSound SfxrHurt(int seed);
110
+struct SfxrSound SfxrPowerup(int seed);
111
+struct SfxrSound SfxrExplosion(int seed);
112
+struct SfxrSound SfxrLaser(int seed);
113
+struct SfxrSound SfxrPickup(int seed);
114
+
115
+#ifdef __cplusplus
116
+}
117
+#endif
118
+
119
+#endif

+ 16
- 0
meson.build View File

@@ -0,0 +1,16 @@
1
+project('bepx', 'c', default_options : ['default_library=static', 'c_std=gnu89'])
2
+incdir = include_directories('include')
3
+
4
+libbepx = library('bepx', 'src/sfxr.c', 'src/bepx.c', include_directories : incdir)
5
+bepx_dep = declare_dependency(link_with : libbepx, include_directories : incdir)
6
+
7
+if not meson.is_subproject()
8
+
9
+#Basic test binary
10
+executable('bepxbasic', 'src/examples/basic.c', include_directories : incdir, dependencies: bepx_dep)
11
+
12
+#Complex test binary
13
+executable('bepxtest', 'src/examples/test.c', include_directories : incdir, dependencies: [bepx_dep])
14
+
15
+endif
16
+

+ 616
- 0
src/sfxr.c View File

@@ -0,0 +1,616 @@
1
+/*
2
+	Copyright (c) 2007 Tomas Pettersson <drpetter@gmail.com>
3
+
4
+	Permission is hereby granted, free of charge, to any person obtaining a copy
5
+	of this software and associated documentation files (the "Software"), to deal
6
+	in the Software without restriction, including without limitation the rights
7
+	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+	copies of the Software, and to permit persons to whom the Software is
9
+	furnished to do so, subject to the following conditions:
10
+
11
+	The above copyright notice and this permission notice shall be included in
12
+	all copies or substantial portions of the Software.
13
+
14
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+	THE SOFTWARE.
21
+*/
22
+
23
+#include "sfxr.h"
24
+
25
+static Sfxr sfxr;
26
+
27
+#include <stdio.h>
28
+#include <stdlib.h>
29
+#include <math.h>
30
+#include <stdint.h>
31
+
32
+float sfxr_frnd(float range)
33
+{
34
+	return (float)rnd(10000)/10000*range;
35
+}
36
+
37
+void SfxrResetParams()
38
+{
39
+	sfxr.wave_type=0;
40
+
41
+	sfxr.p_base_freq=0.3f;
42
+	sfxr.p_freq_limit=0.0f;
43
+	sfxr.p_freq_ramp=0.0f;
44
+	sfxr.p_freq_dramp=0.0f;
45
+	sfxr.p_duty=0.0f;
46
+	sfxr.p_duty_ramp=0.0f;
47
+
48
+	sfxr.p_vib_strength=0.0f;
49
+	sfxr.p_vib_speed=0.0f;
50
+	sfxr.p_vib_delay=0.0f;
51
+
52
+	sfxr.p_env_attack=0.0f;
53
+	sfxr.p_env_sustain=0.3f;
54
+	sfxr.p_env_decay=0.4f;
55
+	sfxr.p_env_punch=0.0f;
56
+
57
+	sfxr.filter_on=0;
58
+	sfxr.p_lpf_resonance=0.0f;
59
+	sfxr.p_lpf_freq=1.0f;
60
+	sfxr.p_lpf_ramp=0.0f;
61
+	sfxr.p_hpf_freq=0.0f;
62
+	sfxr.p_hpf_ramp=0.0f;
63
+
64
+	sfxr.p_pha_offset=0.0f;
65
+	sfxr.p_pha_ramp=0.0f;
66
+
67
+	sfxr.p_repeat_speed=0.0f;
68
+
69
+	sfxr.p_arp_speed=0.0f;
70
+	sfxr.p_arp_mod=0.0f;
71
+
72
+	sfxr.master_vol=0.05f;
73
+	sfxr.sound_vol=0.5f;
74
+
75
+	sfxr.filesample=0.0f;
76
+
77
+	sfxr.playing_sample=0;
78
+	sfxr.samples_played=0;
79
+}
80
+
81
+
82
+void SfxrResetSample(int restart)
83
+{
84
+	if(!restart) {
85
+		sfxr.phase=0;
86
+	}
87
+	sfxr.fperiod=100.0/(sfxr.p_base_freq*sfxr.p_base_freq+0.001);
88
+	sfxr.period=(int)sfxr.fperiod;
89
+	sfxr.fmaxperiod=100.0/(sfxr.p_freq_limit*sfxr.p_freq_limit+0.001);
90
+	sfxr.fslide=1.0-pow((double)sfxr.p_freq_ramp, 3.0)*0.01;
91
+	sfxr.fdslide=-pow((double)sfxr.p_freq_dramp, 3.0)*0.000001;
92
+	sfxr.square_duty=0.5f-sfxr.p_duty*0.5f;
93
+	sfxr.square_slide=-sfxr.p_duty_ramp*0.00005f;
94
+	if(sfxr.p_arp_mod>=0.0f) {
95
+		sfxr.arp_mod=1.0-pow((double)sfxr.p_arp_mod, 2.0)*0.9;
96
+	}
97
+	else {
98
+		sfxr.arp_mod=1.0+pow((double)sfxr.p_arp_mod, 2.0)*10.0;
99
+	}
100
+	sfxr.arp_time=0;
101
+	sfxr.arp_limit=(int)(pow(1.0f-sfxr.p_arp_speed, 2.0f)*20000+32);
102
+	if(sfxr.p_arp_speed==1.0f) {
103
+		sfxr.arp_limit=0;
104
+	}
105
+	if(!restart)
106
+	{
107
+		// reset filter
108
+		sfxr.fltp=0.0f;
109
+		sfxr.fltdp=0.0f;
110
+		sfxr.fltw=pow(sfxr.p_lpf_freq, 3.0f)*0.1f;
111
+		sfxr.fltw_d=1.0f+sfxr.p_lpf_ramp*0.0001f;
112
+		sfxr.fltdmp=5.0f/(1.0f+pow(sfxr.p_lpf_resonance, 2.0f)*20.0f)*(0.01f+sfxr.fltw);
113
+		if(sfxr.fltdmp>0.8f) sfxr.fltdmp=0.8f;
114
+		sfxr.fltphp=0.0f;
115
+		sfxr.flthp=pow(sfxr.p_hpf_freq, 2.0f)*0.1f;
116
+		sfxr.flthp_d=1.0+sfxr.p_hpf_ramp*0.0003f;
117
+		// reset vibrato
118
+		sfxr.vib_phase=0.0f;
119
+		sfxr.p_vib_speed=pow(sfxr.p_vib_speed, 2.0f)*0.01f;
120
+		sfxr.vib_amp=sfxr.p_vib_strength*0.5f;
121
+		// reset envelope
122
+		sfxr.env_vol=0.0f;
123
+		sfxr.env_stage=0;
124
+		sfxr.env_time=0;
125
+		sfxr.env_length[0]=(int)(sfxr.p_env_attack*sfxr.p_env_attack*100000.0f);
126
+		sfxr.env_length[1]=(int)(sfxr.p_env_sustain*sfxr.p_env_sustain*100000.0f);
127
+		sfxr.env_length[2]=(int)(sfxr.p_env_decay*sfxr.p_env_decay*100000.0f);
128
+
129
+		sfxr.fphase=pow(sfxr.p_pha_offset, 2.0f)*1020.0f;
130
+		if(sfxr.p_pha_offset<0.0f) sfxr.fphase=-sfxr.fphase;
131
+		sfxr.fdphase=pow(sfxr.p_pha_ramp, 2.0f)*1.0f;
132
+		if(sfxr.p_pha_ramp<0.0f) sfxr.fdphase=-sfxr.fdphase;
133
+		sfxr.iphase=abs((int)sfxr.fphase);
134
+		sfxr.ipp=0;
135
+		int i;
136
+		for(i=0;i<1024;i++) {
137
+			sfxr.phaser_buffer[i]=0.0f;
138
+		}
139
+
140
+		for(i=0;i<32;i++) {
141
+			sfxr.noise_buffer[i]=sfxr_frnd(2.0f)-1.0f;
142
+		}
143
+
144
+		sfxr.rep_time=0;
145
+		sfxr.rep_limit=(int)(pow(1.0f-sfxr.p_repeat_speed, 2.0f)*20000+32);
146
+		if(sfxr.p_repeat_speed==0.0f) {
147
+			sfxr.rep_limit=0;
148
+		}
149
+	}
150
+}
151
+
152
+
153
+void SfxrSynthSample(int length, unsigned char* buffer, FILE* file)
154
+{
155
+	int i;
156
+	for(i=0;i<length;i++)
157
+	{
158
+		if(!sfxr.playing_sample) {
159
+			break;
160
+		}
161
+
162
+		sfxr.rep_time++;
163
+		if(sfxr.rep_limit!=0 && sfxr.rep_time>=sfxr.rep_limit)
164
+		{
165
+			sfxr.rep_time=0;
166
+			SfxrResetSample(1);
167
+		}
168
+
169
+		// frequency envelopes/arpeggios
170
+		sfxr.arp_time++;
171
+		if(sfxr.arp_limit!=0 && sfxr.arp_time>=sfxr.arp_limit)
172
+		{
173
+			sfxr.arp_limit=0;
174
+			sfxr.fperiod*=sfxr.arp_mod;
175
+		}
176
+		sfxr.fslide+=sfxr.fdslide;
177
+		sfxr.fperiod*=sfxr.fslide;
178
+		if(sfxr.fperiod>sfxr.fmaxperiod)
179
+		{
180
+			sfxr.fperiod=sfxr.fmaxperiod;
181
+			if(sfxr.p_freq_limit>0.0f) {
182
+				sfxr.playing_sample=0;
183
+			}
184
+		}
185
+		float rfperiod=sfxr.fperiod;
186
+		if(sfxr.vib_amp>0.0f)
187
+		{
188
+			sfxr.vib_phase+=sfxr.p_vib_speed;
189
+			rfperiod=sfxr.fperiod*(1.0+sin(sfxr.vib_phase)*sfxr.vib_amp);
190
+		}
191
+		sfxr.period=(int)rfperiod;
192
+		if(sfxr.period<8) sfxr.period=8;
193
+		sfxr.square_duty+=sfxr.square_slide;
194
+		if(sfxr.square_duty<0.0f) sfxr.square_duty=0.0f;
195
+		if(sfxr.square_duty>0.5f) sfxr.square_duty=0.5f;
196
+		// volume envelope
197
+		sfxr.env_time++;
198
+		if(sfxr.env_time>sfxr.env_length[sfxr.env_stage])
199
+		{
200
+			sfxr.env_time=0;
201
+			sfxr.env_stage++;
202
+			if(sfxr.env_stage==3) {
203
+				sfxr.playing_sample=0;
204
+			}
205
+		}
206
+		if(sfxr.env_stage==0) {
207
+			sfxr.env_vol=(float)sfxr.env_time/sfxr.env_length[0];
208
+		}
209
+		if(sfxr.env_stage==1) {
210
+			sfxr.env_vol=1.0f+pow(1.0f-(float)sfxr.env_time/sfxr.env_length[1], 1.0f)*2.0f*sfxr.p_env_punch;
211
+		}
212
+		if(sfxr.env_stage==2) {
213
+			sfxr.env_vol=1.0f-(float)sfxr.env_time/sfxr.env_length[2];
214
+		}
215
+
216
+		// phaser step
217
+		sfxr.fphase+=sfxr.fdphase;
218
+		sfxr.iphase=abs((int)sfxr.fphase);
219
+		if(sfxr.iphase>1023) sfxr.iphase=1023;
220
+
221
+		if(sfxr.flthp_d!=0.0f)
222
+		{
223
+			sfxr.flthp*=sfxr.flthp_d;
224
+			if(sfxr.flthp<0.00001f) sfxr.flthp=0.00001f;
225
+			if(sfxr.flthp>0.1f) sfxr.flthp=0.1f;
226
+		}
227
+
228
+		float ssample=0.0f;
229
+		int si;
230
+		for(si=0;si<8;si++) // 8x supersampling
231
+		{
232
+			float sample=0.0f;
233
+			sfxr.phase++;
234
+			if(sfxr.phase>=sfxr.period)
235
+			{
236
+				//phase=0;
237
+				sfxr.phase%=sfxr.period;
238
+				if(sfxr.wave_type==3) {
239
+					for(i=0;i<32;i++) {
240
+						sfxr.noise_buffer[i]=sfxr_frnd(2.0f)-1.0f;
241
+					}
242
+				}
243
+			}
244
+			// base waveform
245
+			float fp=(float)sfxr.phase/sfxr.period;
246
+			switch(sfxr.wave_type)
247
+			{
248
+			case 0: // square
249
+				if(fp<sfxr.square_duty) {
250
+					sample=0.5f;
251
+				}
252
+				else {
253
+					sample=-0.5f;
254
+				}
255
+				break;
256
+			case 1: // sawtooth
257
+				sample=1.0f-fp*2;
258
+				break;
259
+			case 2: // sine
260
+				sample=(float)sin(fp*2*PI);
261
+				break;
262
+			case 3: // noise
263
+				sample=sfxr.noise_buffer[sfxr.phase*32/sfxr.period];
264
+				break;
265
+			}
266
+			// lp filter
267
+			float pp=sfxr.fltp;
268
+			sfxr.fltw*=sfxr.fltw_d;
269
+			if(sfxr.fltw<0.0f) sfxr.fltw=0.0f;
270
+			if(sfxr.fltw>0.1f) sfxr.fltw=0.1f;
271
+			if(sfxr.p_lpf_freq!=1.0f)
272
+			{
273
+				sfxr.fltdp+=(sample-sfxr.fltp)*sfxr.fltw;
274
+				sfxr.fltdp-=sfxr.fltdp*sfxr.fltdmp;
275
+			}
276
+			else
277
+			{
278
+				sfxr.fltp=sample;
279
+				sfxr.fltdp=0.0f;
280
+			}
281
+			sfxr.fltp+=sfxr.fltdp;
282
+			// hp filter
283
+			sfxr.fltphp+=sfxr.fltp-pp;
284
+			sfxr.fltphp-=sfxr.fltphp*sfxr.flthp;
285
+			sample=sfxr.fltphp;
286
+			// phaser
287
+			sfxr.phaser_buffer[sfxr.ipp&1023]=sample;
288
+			sample+=sfxr.phaser_buffer[(sfxr.ipp-sfxr.iphase+1024)&1023];
289
+			sfxr.ipp=(sfxr.ipp+1)&1023;
290
+			// final accumulation and envelope application
291
+			ssample+=sample*sfxr.env_vol;
292
+		}
293
+		ssample=ssample/8*sfxr.master_vol;
294
+
295
+		ssample*=2.0f*sfxr.sound_vol;
296
+
297
+		if(buffer != NULL)
298
+		{
299
+			// 44100Hz 16 bits
300
+			ssample*=4.0f; // arbitrary gain to get reasonable output volume...
301
+			if(ssample>1.0f) ssample=1.0f;
302
+			if(ssample<-1.0f) ssample=-1.0f;
303
+
304
+			sfxr.filesample+=ssample;
305
+			unsigned short isample=(unsigned short)(sfxr.filesample*32000);
306
+			unsigned char c1 = (unsigned char)((isample & 0xFF00) >> 8);
307
+			unsigned char c2 = (unsigned char)(isample & 0x00FF);
308
+			buffer[sfxr.buffer_byteswritten++] = c2;
309
+			buffer[sfxr.buffer_byteswritten++] = c1;
310
+			sfxr.filesample=0.0f;
311
+		}
312
+		if(file!=NULL)
313
+		{
314
+			ssample*=4.0f; // arbitrary gain to get reasonable output volume...
315
+			if(ssample>1.0f) ssample=1.0f;
316
+			if(ssample<-1.0f) ssample=-1.0f;
317
+			sfxr.filesample+=ssample;
318
+			short isample=(short)(sfxr.filesample*32000);
319
+			fwrite(&isample, 1, 2, file);
320
+			sfxr.filesample=0.0f;
321
+			sfxr.file_bytesswritten+=2;
322
+		}
323
+
324
+		sfxr.samples_played++;
325
+	}
326
+}
327
+
328
+void SfxrPlaySample(unsigned char* buffer, FILE* file) {
329
+	SfxrResetSample(0);
330
+	sfxr.samples_played=0;
331
+	sfxr.playing_sample=1;
332
+	while(sfxr.playing_sample) {
333
+		SfxrSynthSample(256, buffer, file);
334
+	}
335
+}
336
+
337
+
338
+
339
+int SfxrCalculateLength() {
340
+	SfxrPlaySample(NULL, NULL);
341
+	return sfxr.samples_played * 2;
342
+}
343
+
344
+
345
+struct SfxrSound SfxrToBuffer() {
346
+	struct SfxrSound sound;
347
+	sound.length = SfxrCalculateLength();
348
+	sound.data = (unsigned char*) malloc(sound.length);
349
+
350
+	sfxr.buffer_byteswritten=0;
351
+	sfxr.file_bytesswritten=0;
352
+	sfxr.filesample=0.0f;
353
+
354
+	SfxrPlaySample(sound.data, NULL);
355
+	return sound;
356
+}
357
+
358
+
359
+int SfxrToWAV(const char* filename)
360
+{
361
+	FILE* foutput=fopen(filename, "wb");
362
+	if(!foutput) {
363
+		return 0;
364
+	}
365
+	// write wav header
366
+	unsigned int dword=0;
367
+	unsigned short word=0;
368
+	const int wav_bits=16;
369
+	const int wav_freq=44100;
370
+
371
+	fwrite("RIFF", 4, 1, foutput); // "RIFF"
372
+	dword=0;
373
+	fwrite(&dword, 1, 4, foutput); // remaining file size
374
+	fwrite("WAVE", 4, 1, foutput); // "WAVE"
375
+
376
+	fwrite("fmt ", 4, 1, foutput); // "fmt "
377
+	dword=16;
378
+	fwrite(&dword, 1, 4, foutput); // chunk size
379
+	word=1;
380
+	fwrite(&word, 1, 2, foutput); // compression code
381
+	word=1;
382
+	fwrite(&word, 1, 2, foutput); // channels
383
+	dword=wav_freq;
384
+	fwrite(&dword, 1, 4, foutput); // sample rate
385
+	dword=wav_freq*wav_bits/8;
386
+	fwrite(&dword, 1, 4, foutput); // bytes/sec
387
+	word=wav_bits/8;
388
+	fwrite(&word, 1, 2, foutput); // block align
389
+	word=wav_bits;
390
+	fwrite(&word, 1, 2, foutput); // bits per sample
391
+
392
+	fwrite("data", 4, 1, foutput); // "data"
393
+	dword=0;
394
+	int foutstream_datasize=ftell(foutput);
395
+	fwrite(&dword, 1, 4, foutput); // chunk size
396
+
397
+	// write sample data
398
+	sfxr.file_bytesswritten=0;
399
+	sfxr.filesample=0.0f;
400
+	SfxrPlaySample(NULL, foutput);
401
+
402
+	// seek back to header and write size info
403
+	fseek(foutput, 4, SEEK_SET);
404
+	dword=0;
405
+	dword=foutstream_datasize-4+sfxr.file_bytesswritten;
406
+	fwrite(&dword, 1, 4, foutput); // remaining file size
407
+	fseek(foutput, foutstream_datasize, SEEK_SET);
408
+	dword=sfxr.file_bytesswritten;
409
+	fwrite(&dword, 1, 4, foutput); // chunk size (data)
410
+	fclose(foutput);
411
+
412
+	return 1;
413
+}
414
+
415
+
416
+struct SfxrSound SfxrPickup(int seed) {
417
+	srand(seed);
418
+	SfxrResetParams();
419
+
420
+	sfxr.p_base_freq=0.4f+sfxr_frnd(0.5f);
421
+	sfxr.p_env_attack=0.0f;
422
+	sfxr.p_env_sustain=sfxr_frnd(0.1f);
423
+	sfxr.p_env_decay=0.1f+sfxr_frnd(0.4f);
424
+	sfxr.p_env_punch=0.3f+sfxr_frnd(0.3f);
425
+	if(rnd(1))
426
+	{
427
+		sfxr.p_arp_speed=0.5f+sfxr_frnd(0.2f);
428
+		sfxr.p_arp_mod=0.2f+sfxr_frnd(0.4f);
429
+	}
430
+	return SfxrToBuffer();
431
+}
432
+
433
+struct SfxrSound SfxrLaser(int seed) {
434
+	srand(seed);
435
+	SfxrResetParams();
436
+
437
+	sfxr.wave_type=rnd(2);
438
+	if(sfxr.wave_type==2 && rnd(1)) {
439
+		sfxr.wave_type=rnd(1);
440
+	}
441
+	sfxr.p_base_freq=0.5f+sfxr_frnd(0.5f);
442
+	sfxr.p_freq_limit=sfxr.p_base_freq-0.2f-sfxr_frnd(0.6f);
443
+	if(sfxr.p_freq_limit<0.2f) sfxr.p_freq_limit=0.2f;
444
+	sfxr.p_freq_ramp=-0.15f-sfxr_frnd(0.2f);
445
+	if(rnd(2)==0)
446
+	{
447
+		sfxr.p_base_freq=0.3f+sfxr_frnd(0.6f);
448
+		sfxr.p_freq_limit=sfxr_frnd(0.1f);
449
+		sfxr.p_freq_ramp=-0.35f-sfxr_frnd(0.3f);
450
+	}
451
+	if(rnd(1))
452
+	{
453
+		sfxr.p_duty=sfxr_frnd(0.5f);
454
+		sfxr.p_duty_ramp=sfxr_frnd(0.2f);
455
+	}
456
+	else
457
+	{
458
+		sfxr.p_duty=0.4f+sfxr_frnd(0.5f);
459
+		sfxr.p_duty_ramp=-sfxr_frnd(0.7f);
460
+	}
461
+	sfxr.p_env_attack=0.0f;
462
+	sfxr.p_env_sustain=0.1f+sfxr_frnd(0.2f);
463
+	sfxr.p_env_decay=sfxr_frnd(0.4f);
464
+	if(rnd(1)) {
465
+		sfxr.p_env_punch=sfxr_frnd(0.3f);
466
+	}
467
+	if(rnd(2)==0)
468
+	{
469
+		sfxr.p_pha_offset=sfxr_frnd(0.2f);
470
+		sfxr.p_pha_ramp=-sfxr_frnd(0.2f);
471
+	}
472
+	if(rnd(1)) {
473
+		sfxr.p_hpf_freq=sfxr_frnd(0.3f);
474
+	}
475
+	return SfxrToBuffer();
476
+}
477
+
478
+
479
+
480
+struct SfxrSound SfxrExplosion(int seed) {
481
+	srand(seed);
482
+	SfxrResetParams();
483
+
484
+	sfxr.wave_type=3;
485
+	if(rnd(1))
486
+	{
487
+		sfxr.p_base_freq=0.1f+sfxr_frnd(0.4f);
488
+		sfxr.p_freq_ramp=-0.1f+sfxr_frnd(0.4f);
489
+	}
490
+	else
491
+	{
492
+		sfxr.p_base_freq=0.2f+sfxr_frnd(0.7f);
493
+		sfxr.p_freq_ramp=-0.2f-sfxr_frnd(0.2f);
494
+	}
495
+	sfxr.p_base_freq*=sfxr.p_base_freq;
496
+	if(rnd(4)==0) {
497
+		sfxr.p_freq_ramp=0.0f;
498
+	}
499
+	if(rnd(2)==0) {
500
+		sfxr.p_repeat_speed=0.3f+sfxr_frnd(0.5f);
501
+	}
502
+	sfxr.p_env_attack=0.0f;
503
+	sfxr.p_env_sustain=0.1f+sfxr_frnd(0.3f);
504
+	sfxr.p_env_decay=sfxr_frnd(0.5f);
505
+	if(rnd(1)==0)
506
+	{
507
+		sfxr.p_pha_offset=-0.3f+sfxr_frnd(0.9f);
508
+		sfxr.p_pha_ramp=-sfxr_frnd(0.3f);
509
+	}
510
+	sfxr.p_env_punch=0.2f+sfxr_frnd(0.6f);
511
+	if(rnd(1))
512
+	{
513
+		sfxr.p_vib_strength=sfxr_frnd(0.7f);
514
+		sfxr.p_vib_speed=sfxr_frnd(0.6f);
515
+	}
516
+	if(rnd(2)==0)
517
+	{
518
+		sfxr.p_arp_speed=0.6f+sfxr_frnd(0.3f);
519
+		sfxr.p_arp_mod=0.8f-sfxr_frnd(1.6f);
520
+	}
521
+	return SfxrToBuffer();
522
+}
523
+
524
+
525
+struct SfxrSound SfxrPowerup(int seed) {
526
+	srand(seed);
527
+	SfxrResetParams();
528
+
529
+	if(rnd(1)) {
530
+		sfxr.wave_type=1;
531
+	}
532
+	else {
533
+		sfxr.p_duty=sfxr_frnd(0.6f);
534
+	}
535
+	if(rnd(1))
536
+	{
537
+		sfxr.p_base_freq=0.2f+sfxr_frnd(0.3f);
538
+		sfxr.p_freq_ramp=0.1f+sfxr_frnd(0.4f);
539
+		sfxr.p_repeat_speed=0.4f+sfxr_frnd(0.4f);
540
+	}
541
+	else
542
+	{
543
+		sfxr.p_base_freq=0.2f+sfxr_frnd(0.3f);
544
+		sfxr.p_freq_ramp=0.05f+sfxr_frnd(0.2f);
545
+		if(rnd(1))
546
+		{
547
+			sfxr.p_vib_strength=sfxr_frnd(0.7f);
548
+			sfxr.p_vib_speed=sfxr_frnd(0.6f);
549
+		}
550
+	}
551
+	sfxr.p_env_attack=0.0f;
552
+	sfxr.p_env_sustain=sfxr_frnd(0.4f);
553
+	sfxr.p_env_decay=0.1f+sfxr_frnd(0.4f);
554
+	return SfxrToBuffer();
555
+}
556
+
557
+
558
+struct SfxrSound SfxrHurt(int seed) {
559
+	srand(seed);
560
+	SfxrResetParams();
561
+
562
+	sfxr.wave_type=rnd(2);
563
+	if(sfxr.wave_type==2) {
564
+		sfxr.wave_type=3;
565
+	}
566
+	if(sfxr.wave_type==0) {
567
+		sfxr.p_duty=sfxr_frnd(0.6f);
568
+	}
569
+	sfxr.p_base_freq=0.2f+sfxr_frnd(0.6f);
570
+	sfxr.p_freq_ramp=-0.3f-sfxr_frnd(0.4f);
571
+	sfxr.p_env_attack=0.0f;
572
+	sfxr.p_env_sustain=sfxr_frnd(0.1f);
573
+	sfxr.p_env_decay=0.1f+sfxr_frnd(0.2f);
574
+	if(rnd(1)) {
575
+		sfxr.p_hpf_freq=sfxr_frnd(0.3f);
576
+	}
577
+	return SfxrToBuffer();
578
+}
579
+
580
+
581
+struct SfxrSound SfxrJump(int seed) {
582
+	srand(seed);
583
+	SfxrResetParams();
584
+
585
+	sfxr.wave_type=0;
586
+	sfxr.p_duty=sfxr_frnd(0.6f);
587
+	sfxr.p_base_freq=0.3f+sfxr_frnd(0.3f);
588
+	sfxr.p_freq_ramp=0.1f+sfxr_frnd(0.2f);
589
+	sfxr.p_env_attack=0.0f;
590
+	sfxr.p_env_sustain=0.1f+sfxr_frnd(0.3f);
591
+	sfxr.p_env_decay=0.1f+sfxr_frnd(0.2f);
592
+	if(rnd(1)) {
593
+		sfxr.p_hpf_freq=sfxr_frnd(0.3f);
594
+	}
595
+	if(rnd(1)) {
596
+		sfxr.p_lpf_freq=1.0f-sfxr_frnd(0.6f);
597
+	}
598
+	return SfxrToBuffer();
599
+}
600
+
601
+
602
+struct SfxrSound SfxrBlip(int seed) {
603
+	srand(seed);
604
+	SfxrResetParams();
605
+
606
+	sfxr.wave_type=rnd(1);
607
+	if(sfxr.wave_type==0) {
608
+		sfxr.p_duty=sfxr_frnd(0.6f);
609
+	}
610
+	sfxr.p_base_freq=0.2f+sfxr_frnd(0.4f);
611
+	sfxr.p_env_attack=0.0f;
612
+	sfxr.p_env_sustain=0.1f+sfxr_frnd(0.1f);
613
+	sfxr.p_env_decay=sfxr_frnd(0.2f);
614
+	sfxr.p_hpf_freq=0.1f;
615
+	return SfxrToBuffer();
616
+}

Loading…
Cancel
Save