File: AY_UGen.cpp

package info (click to toggle)
supercollider-sc3-plugins 3.7.1~repack-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 14,332 kB
  • ctags: 11,704
  • sloc: cpp: 140,180; lisp: 14,746; ansic: 2,133; xml: 86; makefile: 82; haskell: 21; sh: 8
file content (140 lines) | stat: -rw-r--r-- 3,729 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "SC_PlugIn.h"


#include "ayemu.h"



static InterfaceTable *ft;

struct AY : public Unit
{
	ayemu_ay_t * m_ay;
	unsigned char * m_audiobuf; // The integer audiobuf that the emulator will write to.
	size_t m_audiobufsize;
};

// declare unit generator functions
extern "C"
{
	void load(InterfaceTable *inTable);
	void AY_next(AY *unit, int inNumSamples);
	void AY_Ctor(AY* unit);
	void AY_Dtor(AY* unit);
};

//////////////////////////////////////////////////////////////////

void AY_Ctor(AY* unit)
{
	SETCALC(AY_next);

	// initialize the emulator etc.

	ayemu_chip_t chiptype = ((int) ZIN0(10)) == 1 ? AYEMU_YM : AYEMU_AY;

	// the emulator's output settings
	int freq = SAMPLERATE;
	int chans = 1;
	int bits = 8;//16;

	// The audiobufsize is the number of bytes to store the 16-bit mono integer output for one control block.
	int audiobufsize = BUFLENGTH * chans * (bits >> 3);
	unsigned char * audiobuf = (unsigned char *) RTAlloc(unit->mWorld, audiobufsize);

	ayemu_ay_t * ay = (ayemu_ay_t *) RTAlloc(unit->mWorld, sizeof(ayemu_ay_t));
	memset(ay, 0, sizeof(ayemu_ay_t));

	ayemu_init(ay);

	ayemu_set_chip_type(ay, chiptype, NULL);
	//ayemu_set_chip_freq(ay, freq);
	ayemu_set_sound_format(ay, freq, chans, bits);



	unit->m_audiobuf		= audiobuf;
	unit->m_ay				= ay;
	unit->m_audiobufsize	= audiobufsize;

	// calculate one sample of output.
	AY_next(unit, 1);
}

void AY_Dtor(AY* unit)
{
	RTFree(unit->mWorld, unit->m_ay);
	RTFree(unit->mWorld, unit->m_audiobuf);
}

void AY_next(AY *unit, int inNumSamples)
{
	unsigned char regs[14];

	float *out = OUT(0);

	// Retrieve state
	ayemu_ay_t * ay	= unit->m_ay;
	unsigned char * audiobuf	= unit->m_audiobuf;
	size_t audiobufsize	= unit->m_audiobufsize;

	// The chip's inputs.
	// The hard limits are applied here because the library wastes CPU
	//  by outputting lots of warning messages if we exceed the limits.
	int tonea		= sc_max(0, sc_min((int)ZIN0(0), 4095));
	int toneb		= sc_max(0, sc_min((int)ZIN0(1), 4095));
	int tonec		= sc_max(0, sc_min((int)ZIN0(2), 4095));
	int noise		= (int)ZIN0(3);
	int control		= (int)ZIN0(4);
	int vola		= sc_max(0, sc_min((int)ZIN0(5), 31));
	int volb		= sc_max(0, sc_min((int)ZIN0(6), 31));
	int volc		= sc_max(0, sc_min((int)ZIN0(7), 31));
	int envfreq		= sc_max(0, sc_min((int)ZIN0(8), 4095));
	int envstyle	= (int)ZIN0(9);

	// Translate the values into the raw registers
	regs[0]  = (unsigned char)(tonea & 0xff);
	regs[1]  = (unsigned char)(tonea >> 8);
	regs[2]  = (unsigned char)(toneb & 0xff);
	regs[3]  = (unsigned char)(toneb >> 8);
	regs[4]  = (unsigned char)(tonec & 0xff);
	regs[5]  = (unsigned char)(tonec >> 8);
	regs[6]  = (unsigned char)(noise);
	regs[7]  = (unsigned char)((~control) & 0x3f); 	/* invert bits 0-5 */
	regs[8]  = (unsigned char)(vola); 		/* included bit 4 */
	regs[9]  = (unsigned char)(volb);
	regs[10] = (unsigned char)(volc);
	regs[11] = (unsigned char)(envfreq & 0xff);
	regs[12] = (unsigned char)(envfreq >> 8);
	regs[13] = (unsigned char)(envstyle);

//	Print("vola: %d\n", regs[8]);
//	Print("volb: %d\n", regs[9]);
//	Print("volc: %d\n", regs[10]);

	// Now let's pump that chip
	ayemu_set_regs(ay, regs);
	ayemu_gen_sound(ay, audiobuf, audiobufsize);

	//Print("AY:::    ay->Amp_Global is %d\n", ay->Amp_Global);


	// Convert the output from 16-bit to float, and write to output
	int bufreadpos=0;
	for (int i=0; i < BUFLENGTH; ++i)
	{
//		out[i] = ((audiobuf[bufreadpos++] & 0x00FF) | (audiobuf[bufreadpos++] << 8)) * 3.0517578125e-05f;
//		Print(" {%u}", audiobuf[bufreadpos]);
		out[i] = (audiobuf[bufreadpos++] - 128) * 0.0078125f; // 1/128
	}

}

////////////////////////////////////////////////////////////////////

PluginLoad(AY)
{
	ft = inTable;

	DefineDtorUnit(AY);
}