~hp/moony.lv2

869023d18abb47a3a6da62b3245f1344d6e3dfcb — Hanspeter Portner 1 year, 26 days ago c94e698
Add 'Entropy' function to API

Gets a uint32_t from a ringbuffer (1024 elements), which is continuously
filled from the worker thread from the system's entropy source.

Fixes: https://todo.open-music-kontrollers.ch/~hp/issues/10
6 files changed, 106 insertions(+), 3 deletions(-)

M VERSION
M api/api.c
M api/api_vm.h
M include/moony.h
M manual/manual.html.in
M test/moony_test.lua
M VERSION => VERSION +1 -1
@@ 1,1 1,1 @@
0.41.15
0.41.19

M api/api.c => api/api.c +70 -1
@@ 211,6 211,27 @@ _lvoice_map(lua_State *L)
}

__realtime static int
_lentropy(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));

	size_t sz;
	const uint32_t *val;
	if((val = varchunk_read_request(moony->entropy, &sz)))
	{
		lua_pushinteger(L, *val);

		varchunk_read_advance(moony->entropy);
	}
	else
	{
		lua_pushnil(L);
	}

	return 1;
}

__realtime static int
_lmidi2cps(lua_State *L)
{
	const lua_Number note = luaL_checknumber(L, 1);


@@ 1028,6 1049,20 @@ static const LV2_State_Interface state_iface = {
	.restore = _state_restore
};

__non_realtime static void
_fill_entropy(moony_t *moony)
{
	uint32_t *val;
	while((val = varchunk_write_request(moony->entropy, sizeof(uint32_t))))
	{
		*val = arc4random();

		//lv2_log_note(&moony->logger, "prefilling entropy %"PRIu32, *val);

		varchunk_write_advance(moony->entropy, sizeof(uint32_t));
	}
}

__non_realtime static LV2_Worker_Status
_work_job(moony_t *moony,
	LV2_Worker_Respond_Function respond,


@@ 1074,6 1109,10 @@ _work_job(moony_t *moony,
		{
			free(job->ptr);
		} break;
		case MOONY_JOB_ENTROPY:
		{
			_fill_entropy(moony);
		} break;
	}

	return LV2_WORKER_SUCCESS;


@@ 1168,6 1207,7 @@ _work_response(LV2_Handle instance, uint32_t size, const void *body)
		case MOONY_JOB_MEM_FREE:
		case MOONY_JOB_VM_FREE:
		case MOONY_JOB_PTR_FREE:
		case MOONY_JOB_ENTROPY:
			break; // never reached
	}



@@ 1263,6 1303,15 @@ moony_init(moony_t *moony, const char *subject, double sample_rate,
		return -1;
	}

	moony->entropy = varchunk_new(0x4000, true);
	if(!moony->entropy)
	{
		fprintf(stderr, "varchunk_new failed\n");
		return -1;
	}

	_fill_entropy(moony);

	moony->mem_size = mem_size;
	moony->testing = testing;
	moony->vm = moony_vm_new(moony->mem_size, testing, moony);


@@ 1532,6 1581,9 @@ moony_deinit(moony_t *moony)

	if(moony->from_dsp)
		varchunk_free(moony->from_dsp);

	if(moony->entropy)
		varchunk_free(moony->entropy);
}

#define _protect_metatable(L, idx) \


@@ 1619,11 1671,16 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
	lua_pushcclosure(L, _lvoice_map, 1);
	lua_setglobal(L, "Blank");

	// Entropy
	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
	lua_pushcclosure(L, _lentropy, 1);
	lua_setglobal(L, "Entropy");

	// lv2.midi2cps
	lua_pushcclosure(L, _lmidi2cps, 0);
	lua_setglobal(L, "midi2cps");

	// lv2cps2midi.
	// lv2cps2midi
	lua_pushcclosure(L, _lcps2midi, 0);
	lua_setglobal(L, "cps2midi");



@@ 2718,5 2775,17 @@ moony_out(moony_t *moony, LV2_Atom_Sequence *notify, uint32_t frames)
	}
#endif

	{
		moony_job_t *req;
		if((req = varchunk_write_request(moony->from_dsp, sizeof(moony_job_t))))
		{
			req->type = MOONY_JOB_ENTROPY;

			varchunk_write_advance(moony->from_dsp, sizeof(moony_job_t));
			if(moony_wake_worker(moony->sched) != LV2_WORKER_SUCCESS)
				moony_trace(moony, "waking worker failed");
		}
	}

	moony->once = false;
}

M api/api_vm.h => api/api_vm.h +2 -1
@@ 58,7 58,8 @@ enum _moony_job_enum_t {
	MOONY_JOB_MEM_FREE,
	MOONY_JOB_VM_ALLOC,
	MOONY_JOB_VM_FREE,
	MOONY_JOB_PTR_FREE
	MOONY_JOB_PTR_FREE,
	MOONY_JOB_ENTROPY
};

struct _moony_job_t {

M include/moony.h => include/moony.h +1 -0
@@ 312,6 312,7 @@ struct _moony_t {
	uint32_t stash_size;

	varchunk_t *from_dsp;
	varchunk_t *entropy;

	latom_driver_hash_t atom_driver_hash [DRIVER_HASH_MAX];


M manual/manual.html.in => manual/manual.html.in +17 -0
@@ 308,6 308,7 @@ pre {

		<li><a href="#util">Utilities</a>
			<ul>
				<li><a href="#util-entropy">Entropy</a></li>
				<li><a href="#util-midi2cps">midi2cps</a></li>
				<li><a href="#util-cps2midi">cps2midi</a></li>
				<li><a href="#util-note">Note</a></li>


@@ 4443,6 4444,22 @@ end</code></pre>
	<p>Various hopefully useful utility functions.</p>
	</div>

		<!-- Entropy -->
		<div class="api-section">
		<h2 id="util-entropy">Entropy</h2>
		<p>Get Entropy from system.</p>

		<dl>
			<dt class="func">Entropy()</dt>
			<dt class="ret">(integer)</dt>
				<dd>random number from system</dd>
		</dl>

		<pre><code data-ref="util-entropy">-- entropy

assert(Entropy() ~= nil)</code></pre>
		</div>

		<!-- midi2cps -->
		<div class="api-section">
		<h2 id="util-midi2cps">midi2cps</h2>

M test/moony_test.lua => test/moony_test.lua +15 -0
@@ 1997,6 1997,21 @@ do
	end
end

-- Entropy
print('[test] Entropy')
do
	for i=1, 1023 do
		local seed = Entropy()
		print(i, seed)
		assert(seed ~= nil)
	end

	for i=1024, 2048 do
		local seed = Entropy()
		assert(seed == nil)
	end
end

-- midi2cps/cps2midi
print('[test] midi2cps/cps2midi')
do