void renderPulse(float[] dest, int nsamples) {
		// This follows the same general pattern as renderTriSaw above, except
		// this time the waveform is a pulse wave with variable pulse width,
		// which means we get very simple integrals. The state machine works
		// the exact same way, see above for description.
		//COVER("Osc pulse");

		// calc helper values
		float f = utof23(freq & 0xffffffffl);
		float gdf = gain / f;
		float col = utof23(brpt & 0xffffffffl);

		float cc121 = gdf * 2.0f * (col - 1.0f) + gain;
		float cc212 = gdf * 2.0f * col - gain;

		this.state = osm_init();

		for (int i = 0; i < nsamples; i++) {
			float p = utof23(cnt & 0xffffffffl);
			float out = 0.0f;

			switch (osm_tick(this.state)) {
				case OSMTC_UP:
					out = gain;
					break;

				case OSMTC_DOWN:
					out = -gain;
					break;

				case OSMTC_UP_DOWN:
					out = gdf * 2.0f * (col - p) + gain;
					break;

				case OSMTC_DOWN_UP:
					out = gdf * 2.0f * p - gain;
					break;

				case OSMTC_UP_DOWN_UP:
					out = cc121;
					break;

				case OSMTC_DOWN_UP_DOWN:
					out = cc212;
					break;

				// INVALID CASES
				default:
					assert (false);
					break;
			}

			output(dest, i, out);
		}
	}