-
-
Notifications
You must be signed in to change notification settings - Fork 23
Home
The goal of this documentation is to describe all aspects of osci-render in detail. If you read this and still have questions that you think should be answered in the documentation, please raise an issue and let me know.
todo
The project select screen is the first thing you'll see when you open osci-render. It's your hub for starting or re-opening projects and for learning about new features in osci-render.
Here, you can open any recent projects, look at the changelog for the latest versions, and open log folders for debugging any errors.
The most common thing you'll be doing here is opening a previous project, or starting a new one with the "Start new project" button.
The changelog mirrors the same changelog linked in GitHub releases. It should be an extensive view of any new changes added in recent versions of osci-render. Older versions are not documented here.
Any contributors to specific versions are mentioned, as well as anybody that suggested the feature or raised the issue :)
Any project that you open in osci-render is saved to a list of recent files that will appear here every time you open osci-render. Clicking on any item in the list will open it in osci-render. Items in the list are ordered by how recently they were opened, so if you open a project at the bottom, it will move to the top the next time you look at the recent files.
The audio from osci-render is very loud on start-up! This is a 'feature' in the sense that the image should ideally be as large as possible when displayed, so we need the volume of the audio to be loud so that it takes up more space.
To mitigate against this, you can start osci-render muted by checking "Start muted" underneath the "Start new project" button. This setting is remembered for when you next open osci-render.
This will have the effect of setting the volume slider in the Effects panel to 0 so that there is no audio. You can then start playing audio by changing the slider value to something above 0. The default volume value is 3 which should create an image that takes up the entire size of the oscilloscope display.
Unfortunately, osci-render is still in very active development and will run into errors! To help fix any bugs or errors, the log files are incredibly useful for me to understand what problems are occurring and isolate the issue to a particular part of the program.
Any error whilst running is saved to these log files, as well as more minor logs to give me extra information whilst debugging.
To open the folder containing error logs, click the "Open log folder" button. This shows you every log created for every time you've run osci-render. There might be a lot in here, and it's fine to delete these if they are taking up space. There is a maximum size of 1MiB for any individual log file, but this is unlikely to ever be reached and most log files are less than 1KiB in size.
When creating an issue for osci-render, always provide a log file to help solve the problem! Please check the log files beforehand if there is any information about your username, machine name, or directory structure that you'd like to keep private.
Osci-render supports the following file types: .obj
, .txt
, .svg
, and .lua
. The default file that opens when you start a new project is a default 3D cube .obj file.
You can open a file using the "Choose File" button in the Main settings panel.
Any file type can be edited when it's opened using the "Edit file" button. This opens a text editor window that allows you to change anything about the file. This could include changing the position of a cube's corner or changing the text displayed.
.obj files are 3D objects that can be displayed as a wireframe mesh in osci-render. The rotation of the object in each axis can be controlled using the 3D .obj settings panel.
Osci-render supports extremely complex 3D objects if you give it enough time to calculate the most efficient way of traversing the 3D object when drawing it on the screen. This process can take a minute or more for complicated objects. For objects with a lot of vertices, you can enable GPU rendering if you have a computer with a decent graphics card to render the movement of the object at a higher framerate. This becomes essential when you are also hiding the hidden edges of an object.
There is a great list of example .obj files available here: https://people.sc.fsu.edu/~jburkardt/data/obj/obj.html
.txt files are the simplest file type. Any text in the file is rendered to the display in the default sans-serif font of your operating system. To change the font being used, as well as the font style (Plain, Bold, or Italic), you can select the different options under View in the menu bar and then "Text File Font" and "Text File Font Style".
.txt files are also the most 'sensible' file to edit in osci-render since any changes made are immediately reflected as text.
.svg files are common vector image formats that look great on an oscilloscope as they are not defined in terms of pixels, but rather shapes and positions. They also naturally trace a path, making the image very crisp with very few jumps of the oscilloscope beam.
A great list of example .svg files is available here: https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/
.lua files in osci-render are used to generate raw audio samples using the Lua programming language. These work differently from the other files since they are a 'micro-program' within osci-render and have a state that you can completely configure yourself.
When you create a .lua file using the Create File button, and then edit the file using Edit File, you will see a simple example script that explains in detail how you can write a program in Lua.
The return type of a Lua program is an array of two values. These correspond to the left and right audio channels of a single audio sample, or the x and y coordinates of a single dot drawn to the screen. These values should fall in the range of -1 to +1, with { -1, -1 }
being the left-most, bottom-most point, { 0, 0 }
being the centre of the display, and { 1, 1 }
being the right-most, top-most point.
The most simple program would return a single dot or audio sample in the centre of the display. This would be silent if you were to listen to it since there is no movement in the image: return { 0, 0 }
step
is the name of a variable available by default which is the current sample number that is being generated. It is incremented every time the script is called, so it starts off with a value of 1 and will increase by one every time the script runs. step
is fundamental when used as a 'phase' or 'theta' when calling mathematical functions that have a periodic output, like math.sin
, math.cos
, or math.tan
.
An example Lua program that draws a simple circle using step
is as follows:
return { math.sin(step / 1000), math.cos(step / 1000) }
Here, we are using the math.sin
and math.cos
functions provided by Lua and detailed more below. A list of other interesting functions in the Lua math
library is here.
The math
library also provides some constants such as math.pi
that are very useful when dealing with rotation.
slider_a
, slider_b
, slider_c
, slider_d
, and slider_e
are other pre-defined variables that all correspond to the value of the corresponding sliders in the .lua file settings. When you change the value of a slider, or the slider's value is being animated by one of the animation effects, you'll see the value of this change.
You can use the slider_X
variables to control various aspects of the program, such as the ratio between frequencies in a Lissajous pattern, or the speed at which something oscillates.
When declaring a new variable, you might find it helpful to be able to set an initial value the first time the script runs, but use the previous value of the variable when it next runs. You can do this simply with the following:
-- sets 'theta' to 0 initially, or the previous value of
-- 'theta' the last time this script ran
theta = theta or 0
This would allow you to replicate the behaviour of step
(i.e. starting at 1 and incrementing every call to the script) by doing:
my_step = my_step or 1
my_step = my_step + 1
A fully comprehensive example of a complicated Lua script project for osci-render can be found here: https://james.ball.sh/docs/osci-seption.osci and the script is also below:
-- a=start point, b=end point, t=drawing progress
function line(a, b, t)
return {
a.x + t * (b.x - a.x),
a.y + t * (b.y - a.y)
}
end
focal_length = slider_c
camera_z = slider_b * 10
-- projects a 3D point into 2D
function project(point)
return {
x=point.x * focal_length / (point.z - camera_z),
y=point.y * focal_length / (point.z - camera_z)
}
end
-- rotates a point in 3D
function rotate(point, rotate_x, rotate_y, rotate_z)
x1 = point.x
y1 = point.y
z1 = point.z
-- rotate around x-axis
cos = math.cos(rotate_x)
sin = math.sin(rotate_x)
y2 = cos * y1 - sin * z1
z2 = sin * y1 + cos * z1
-- rotate around y-axis
cos = math.cos(rotate_y)
sin = math.sin(rotate_y)
x2 = cos * x1 + sin * z2
z3 = -sin * x1 + cos * z2
-- rotate around z-axis
cos = math.cos(rotate_z)
sin = math.sin(rotate_z)
x3 = cos * x2 - sin * y2
y3 = sin * x2 + cos * y2
return {
x=x3,
y=y3,
z=z3
}
end
num_points = 16
-- 3D cube draw path
points = {
{x=-1.0, y=-1.0, z=1.0},
{x=1.0, y=-1.0, z=1.0},
{x=1.0, y=-1.0, z=-1.0},
{x=-1.0, y=-1.0, z=-1.0},
{x=1.0, y=-1.0, z=-1.0},
{x=1.0, y=1.0, z=-1.0},
{x=-1.0, y=1.0, z=-1.0},
{x=-1.0, y=-1.0, z=-1.0},
{x=-1.0, y=-1.0, z=1.0},
{x=1.0, y=-1.0, z=1.0},
{x=1.0, y=1.0, z=1.0},
{x=-1.0, y=1.0, z=1.0},
{x=1.0, y=1.0, z=1.0},
{x=1.0, y=1.0, z=-1.0},
{x=-1.0, y=1.0, z=-1.0},
{x=-1.0, y=1.0, z=1.0}
}
-- percentage of the image that has currently been drawn
drawing_progress = drawing_progress or 0
drawing_progress = drawing_progress + 0.001 * slider_a
progress_cutoff = slider_e
if drawing_progress > progress_cutoff then
drawing_progress = 0
end
-- get the index of the start point of the current line
start_index = math.floor(drawing_progress * num_points + 1)
-- end point of current line is the next in the points table
end_index = start_index + 1
if end_index > num_points then
end_index = 1
end
-- doing this to avoid recomputation for every sample.
-- prev_start ~= start_index == true whenever a new line has started
if prev_start ~= start_index then
rotate_speed = slider_d * step / 1000
-- rotate and project the start and end points
proj_start = project(rotate(points[start_index], rotate_speed, rotate_speed, 0))
proj_end = project(rotate(points[end_index], rotate_speed, rotate_speed, 0))
end
prev_start = start_index
-- work out what the relative progress drawn of the current line is
draw_length = 1.0 / num_points
line_progress = drawing_progress - (start_index - 1) * draw_length
line_progress = num_points * line_progress
return line(proj_start, proj_end, line_progress)
This is 'osci-render inside of osci-render' and generates audio samples to render the default cube that is displayed when you create a new osci-render project.
Every single audio sample is generated with a call to the Lua program you've written. This means at high sample rates (i.e. 192kHz) you will run into performance issues if you are trying to generate complicated sounds as the script is literally running 192,000 times per second! Because of this, you need to take performance into consideration if you are thinking about developing something complex in osci-render.
The example script above is a very good case study for optimising the script for running at a high sample rate. The expensive functions in my program are project
and rotate
. Both of these, but especially rotate
, do a lot of complex maths to rotate the point drawn and then project this into 2D coordinates. If I were to perform this for every single audio sample it would be extremely expensive and the audio samples would not be generated quickly enough.
Instead, I only perform the rotation and projection when the line tracing the shape of the cube changes line. I make the assumption that there isn't much rotation between drawing the start of a line and the end of the line, and so the 2D coordinates of the start and end points don't change whilst the line is drawn. This is a fair assumption to make, as at any audible frequency and reasonable rotation speed the lines are drawn so quickly that there is very little rotation whilst drawing the line.
If it were to take only 0.001 seconds to draw a single line, then I'm only doing expensive computation 1000 times per second, rather than 192,000 times per second if I did this for every audio sample. That's a 192x performance increase for practically nothing!
Re-using computation, or reducing expensive computation to only once every few-hundred audio samples, is the best way to improve performance.
If I were to create a game, physics engine, or anything that required constant computation every 'frame', it's best to only do this computation occasionally rather than every audio sample. You could do this by having the expensive computation in an if
statement using step
:
-- only do the expensive computation if step is a multiple of 400
-- this means it only runs every 400 audio samples (which is still 480 times per second at 192kHz!)
if step % 400 == 0 then
-- expensive computation
end
Osci-render currently doesn't have a dedicated settings menu. Instead, the menu bar provides any settings that you are unlikely to need to use whilst performing or synthesising music. The menu bar is located at the top of the main application after opening a project:
The File menu shows all project-related actions. This includes a list of recent projects, actions to open a project, and also save the current project.
In addition to using the menu, you can also use the following keyboard shortcuts:
- Open Project - Ctrl/Cmd + O
- Save Project - Ctrl/Cmd + S
- Save Project As - Ctrl/Cmd + Shift + S
Audio settings contain options to change the audio device you are outputting to, as well as recording the current audio being synthesised to a .wav file.
You should see a list of different audio devices, as well as the sample rate and number of channels available for each device. The audio devices named "default" are all using Java's sound engine, which has the best-supported audio across different operating systems, however, this has the caveat of not being able to choose a different sound output to your operating system's default. To mitigate this, on Windows and Linux (unfortunately not macOS) you also have access to the rest of the audio devices on your machine.
Osci-render supports multi-channel output at a basic level. If osci-render detects that you have an audio interface with more than 2 outputs, it will allow you to choose these as an option in the list of audio devices. You can then control the value of all additional channels using the "Brightness" slider. This will be an inaudible signal and only makes sense if you are using a DC-coupled audio interface since it's a static signal. This is named "Brightness" as it's currently only a static signal for use with CRT displays that have a Z channel for the intensity of the electron beam.
Osci-render supports high-quality lossless recordings of the audio being synthesised as a .wav file. You can either click "Record" or use the keyboard shortcut Ctrl/Cmd + R to start recording. When recording starts, this menu item will change to say "Stop recording" and when you press it or use Ctrl/Cmd + R again, it will stop recording and ask for you to provide a file name and location to save the .wav file. If no location is provided, osci-render will save it in the folder that it is being run from, to make sure that the recording isn't lost. When a file is saved, the location it has been saved to is detailed at the bottom of the Main settings panel.
You can also create a recording for a fixed length of time using the "Timed recording?" checkbox and then configure how long you want the recording to be using the "Record length" text box. This will automatically stop recording after the time has elapsed, prompting you for a location to save the recording immediately after the recording has finished.
If you want to record the audio with a different bit depth or format, you can also change the "Recording audio sample" from the dropdown. The following audio sample formats are available:
- Unsigned 8-bit integer
- Signed 8-bit integer
- Signed 16-bit integer (default)
- Signed 24-bit integer
- Signed 32-bit integer
You should not notice any significant difference in audio or visual quality, especially past 16-bit. For reference, Java's sound engine (the default for osci-render) will play audio to your audio device using 16-bit signed integer audio samples.
The MIDI settings have a few actions to reset MIDI, and configure the MIDI channel being primarily used for visuals. Read MIDI Control for much more information on controlling sliders
"Reset MIDI Mappings" unbinds any sliders that are currently bound to a MIDI CC channel. This can also be triggered with the keyboard shortcut Ctrl/Cmd + M.
"Stop MIDI Notes" is used to stop all notes that osci-render thinks are being held down. This can happen if the MIDI signals being received are malformed and don't have a 'stop note' or 'release key' message. This should be very uncommon and shouldn't need to be used.
"Reset MIDI" resets osci-render to the state before any MIDI notes are played. This might be needed if you accidentally play a MIDI note and want to go back to the default behaviour when you start osci-render of constantly playing a note.
"Deadzone" increases the area on a slider that snaps to 0 when controlling it with a MIDI CC device. This is needed as MIDI CC messages only have 128 different values, which is not much granularity at all. This might mean there is no position on a MIDI CC slider that has a value of 0. To mitigate against this, the deadzone snaps to 0 when a MIDI CC value is close to the zero point and increasing the deadzone means that it snaps when further away from the zero point.
"Main MIDI Channel" chooses the main MIDI channel used for osci-render's visuals. Osci-render only renders the image you have open at one frequency at a time - so you cannot play chords with a single image. Therefore, this selects which channel should be used to create this image. All other channels are then simple sine waves. For more explanation of this, look at the MIDI Control section.
The "Note Attack" and "Note Decay" are fairly standard options for controlling the sound of the MIDI note. They change the time it takes for a note played to reach full volume, and the time it takes after the note stops for it to be silent respectively. Attack and decay values of 0 will result in harsh notes that instantly start and stop playing.
The View settings control various aspects of how the image looks and how it is rendered on a CRT display. They are more concerned with video rather than audio (though of course, they are one and the same).
"Flip X Direction" and "Flip Y Direction" mirror the image in either the X or Y axis, which can be useful if your CRT display or software has flipped axes.
"Hide Hidden Meshes" is a more experimental setting that hides any edges of a 3D object that should be hidden by the mesh of the object - treating it as a solid object that light cannot pass through. This gives the impression of the object looking more 'real'. This setting is heavily inspired by VAMP by Chris Allen who developed a similar plugin for Blender for use with OsciStudio. This requires a fairly expensive calculation to determine whether each point on a mesh is visible to the camera and this runs in real time. Because of this, don't expect very complicated meshes to render at high framerates when this is enabled.
Below shows an example of the substantial increase in image quality when this is enabled when rendered at the same frequency.
This isn't possible at all on complicated objects unless you are using GPU rendering. Enabling "Render using GPU" utilises the graphics card on your machine to do all the expensive calculations. Rotations of complex 3D objects and projections of each vertex into 2D can all be accelerated with the GPU, as well as the previously mentioned "Hide Hidden Meshes" feature. With the example video above, I get around 4 frames per second when trying to hide hidden edges without using the GPU. This is compared with an uncapped framerate when using GPU rendering!
GPU rendering is disabled by default due to incompatibility with some machines. It uses OpenCL which is already installed on Windows, meaning there shouldn't be any setup required to use it. On macOS and Linux, you might need to first install OpenCL for this to have any effect. On Linux, if you are using Intel(R) integrated graphics, you should be able to install Intel(R) Graphics Compute Runtime to get this working. If anyone using macOS could provide insight into whether this works, please make an issue or email me at [email protected].
The Sliders menu allows you to change the minimum and maximum values that any slider in the interface can have. You can choose a slider to modify by using the dropdown, and then change the minimum and maximum values using the "Min" and "Max" text boxes.
Sliders mapped to MIDI CC channels will use the new range, and any animations will now animate between the new min and max values set. This is the easiest way of making an animation only oscillate between a smaller range of values than the default.
The Window menu currently only has an option to open the Software Oscilloscope.
The Software Oscilloscope, aptly named 'sosci' is the best way to use osci-render if you don't have a real analogue oscilloscope. It uses a modified version of the amazing woscope library by m1el.
NOTE: The software oscilloscope doesn't (currently) work on Safari. Please use Firefox or Chrome!
Clicking on "Open Software Oscilloscope" will open james.ball.sh/oscilloscope in your default browser. If no audio is playing back or osci-render hasn't connected, you'll see a green dot in the centre of the display. As soon as you open osci-render with this webpage open and can hear audio, you'll see the image generated by the software oscilloscope.
Using the two sliders at the top-left, you can configure the intensity/brightness of the beam using the intensity slider, as well as the hue of the lines drawn.
The main settings panel is where you can open new files and folders, as well as edit open files and create new files. There is also text on this panel describing the current frequency, the currently open file, and information about audio recordings.
In the top-left are all the file modification buttons. These allow you to do the following:
- Open one of the supported file types using "Choose File" which opens up a file dialog allowing you to choose a file
- Edit the file in a separate text editor window that is currently open using "Edit File"
- Close the currently open file using "Close File"
- Open a folder containing supported file types using "Choose Folder" which opens all of the files in osci-render
Editing files happens instantaneously and changes are immediately reflected in the visuals and audio. This means you can modify .obj files, for example, from within osci-render and change the position of vertices, or type a sentence and have it be written in real-time when editing .txt files.
When you have multiple files open, you can cycle between them using the 'j' and 'k' keys on your keyboard to move forward and backwards through the list of files. You can also press 'i' to start the playback of all the files so that they cycle automatically. You can then use 'u' and 'o' to change the speed of the playback and press 'i' again to stop playback.
When you open a folder, the files will be opened in alphabetical order, so if you want to cycle through the files in a particular order, you should keep this in mind.
If you close all open files, the file name will change to "No files open!" and any audio will stop.
You can also create new files from within osci-render using the text box and dropdown at the bottom of the panel to type the name and choose the type of the file, and then create it using "Create File". This will add it to the files you currently have open. When you create a file like this, an appropriate demo/example file is created for the file type chosen:
--
-- .lua files can be used to make your own custom audio sources!
-- Lua documentation: https://www.lua.org/docs.html
--
-- All variables are saved between calls to this script.
--
-- Below is a simple example of an audio effect that makes a
-- nice visual on an oscilloscope and shows off some of the
-- functionality available.
--
-- The variable 'step' used below is incremented with every
-- call to this script, starting at 1.
--
-- sets 'theta' to 0 initially, or the previous value of
-- 'theta' the last time this script ran
theta = theta or 0
-- updates 'theta' using 'step'
theta = theta + math.sqrt(step) / 1000000000
-- 'slider_a', 'slider_b', ..., 'slider_e' are controlled by
-- the respective sliders in the .lua file settings
left_scale = 0.3 * slider_a
right_scale = 0.3 * slider_b
-- Returns audio samples that will be played back
return {
-- left audio channel
left_scale * math.tan(theta * step),
-- right audio channel
right_scale * math.tan(theta * step + math.pi / 2)
}
Draws an experimental oscillating tan function.
<svg><path d="M 0,0 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0"/></svg>
Draws a circle.
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6
Draws a 3D cube.
hello
Draws the text hello
.
When recording audio, the text at the bottom of the panel will change to "Recording...", and upon saving the file successfully it will change to the file location where it has been saved.
The current 'actual' frequency of the audio is displayed for each audio channel next to "L/R Frequency". This will potentially be very different to the Target frequency slider as it considers the frequency after all effects have been applied. This is calculated using a Fourier Transform, which works by 'binning' different frequencies, so this number is an approximation of the real frequency you hear.
The Octave slider snaps to specific values between -5 and +5. These values correspond to the number of octave shifts to be applied to the current frequency as specified in the Target frequency slider. Increasing the audio by a single octave has the effect of doubling the target frequency, whereas decreasing the octave halves the frequency.
The Mic Volume slider controls how sensitive microphone input affecting sliders is. If you change the range of this slider using the Sldiers menu item, you can also make the microphone input decrease a slider's value.
The 3D .obj settings panel contains all settings relating to the rotation and focal length of 3D objects in osci-render. Every setting here can be animated and controlled by MIDI.
The focal length slider changes the focal length of the camera looking at the object. Smaller values will make the make look smaller and perspective effects will be stronger, whereas larger values increase the size of the image and make the image look 'flatter'.
The three sliders for 3D rotation, "Rotate x", "Rotate y", and "Rotate z" control the three axes of rotation for the object. When the rotation speed is set to zero, this will change the rotation in that axis without any other animated movement. When the rotation speed is positive, it will rotate in the direction specified by these sliders, and a negative speed moves it in the opposite direction.
"Rotate speed" controls how fast the object rotates according to the three sliders controlling the rotation direction. Currently, the higher the frequency of the image, the faster the object will rotate as each 'frame' is rendered more quickly. This is something that I am unsure whether should be changed so that rotation speed is consistent. It currently has the nice effect of spinning faster when the frequency is higher, but there is no way of having a consistent rotation speed. If you have any feedback on this, please let me know!
"Reset Rotation" sets all of the rotation axes sliders and rotation speed slider to 0 so that the 3D object is in the original default rotation.
You can also control the x and y axes of rotation by moving the mouse if you select "Rotate with Mouse". This moves the x and y slider values between 0 and 1 depending on the position of your mouse within osci-render and can be a nice way of positioning the object. You can press the Esc key once you are in a position you're happy with to disable any more mouse rotation without needing to click on the checkbox again.
Next to the three rotation axes in 3D .obj file settings, and also next to the 3D rotation sliders for the 3D perspective effect, there is the following icon:
When clicking this, it will change to a red colour and the rotation in that axis will not be rotated/animated when the rotation speed is non-zero. This means that you can position the object on one axis and then spin it on another axis - rather than both axes spinning at the same time. You can think of this as setting the rotation speed on that specific axis to 0.
The sliders in this panel are used to control the pre-defined variables available to use in a Lua live-coding script.
Each slider corresponds to the value of a pre-defined variable with a similar name when writing a Lua program. For example, the value of "Slider a" can be accessed as slider_a
in Lua. These can all be animated and controlled with MIDI as you could expect.
"Reset Step Counter" resets the value of the step
pre-defined variable back to the original value of 1. This can be useful if you are writing a Lua program that uses step
as a way of animating through different sounds or visuals - you can 'reset' the animation using this.
The audio effects are one of the most important parts of osci-render. Here, you can make any transformations to the image and audio that you're rendering from the files you've opened.
This covers each in detail, along with a GIF of every effect so you can see the visual effect.
All effects have been designed in a way such that a value of 0 means that the effect is completely disabled and will not change the visuals or audio, whereas higher values apply the effect more.
Every single effect can be animated.
Vector cancelling is one of the least intuitive effects available. It works by negating or 'flipping' the occasional audio sample by multiplying it by -1 in the left/x and right/y audio channels. The value of the slider determines how frequently the audio samples are flipped. The default value (approx. 0.111) flips the audio samples every other sample, and as you increase the slider, it will negate more often, making the mirrored image the prominent one.
This makes use of extremely high-frequency audio so visualisation of this will vary a lot on different CRT displays. It also does not 'accurately' display using the software oscilloscope, so this is really one for you to test with yourself.
This effect has very little effect on the audio, other than the volume. You will hear some artifacts from the extremely high-frequency audio, but otherwise, it's not obvious it's even enabled from the audio alone.
At the default value of around 0.111, you will hear almost nothing, but still get an image on your display. This is because at this value every other sample is inverted and the audio 'cancels' itself out - making it almost silent.
Bit crush makes the image look pixelated by limiting the precision of every audio sample or point drawn to the display. This means that values such as 0.11 or 0.09 might get rounded to 0.1 creating a 'blocky' feel to the visuals and audio.
At small values, the audio doesn't change much whilst the image is clearly different. However, at much larger values, both the image and audio are extremely distorted.
The wobble effect applies a sine wave to the image at a similar frequency to the image. This displaces it with a signal that is almost the same, creating an oscillation or 'wobble' effect. Occasionally, this can apply a sine wave that is exactly the same frequency, removing any oscillation and displacing the image slightly.
You will hear a faint sine wave if your image is being rendered in audible ranges frequencies that gets louder as you increase the value of the slider.
The frequency of the sine wave is calculated when you enable the wobble effect using the actual frequency of the output audio, as reported in the Main settings panel. It is re-calculated whenever you change the file you have open or re-enable the effect.
Smoothing uses a window average over some of the last audio samples to 'smoothen' out the image and reduce any rapid changes in frequency by making sharp corners more curved. The value of the slider increases the size of the window that is used to take an average, making the image smoother.
You can clearly hear the effect this has on the audio, reducing any 'buzzing' or other unwanted artifacts of rapid changes in frequency.
For every other audio sample or point drawn, the vertical shift applies a displacement to the image either in the positive or negative y direction. This means in the first sample drawn, it might increase the y position, and in the next sample, it will decrease the y position. This gives the effect of making horizontal lines 'thicker'.
This is another effect that can vary how it looks a lot depending on what kind of display you use since it takes advantage of very high-frequency audio to change how the image looks, without changing the audio much at all.
Very similar to the vertical shift effect, except now the displacement is in the x-axis. This creates very similar visuals to the vertical shift, but now the vertical lines look thicker.
The translation effect moves the image around the screen according to the values of the translation x and y textboxes. The x textbox controls the horizontal position of the image, and the y textbox controls the vertical position.
As well as changing the value in the textbox, you can also move the object more intuitively using your mouse by selecting the "Translate with Mouse" checkbox. Whilst this is checked, moving your mouse will move the image on the screen. Press Esc to disable the checkbox and leave the image in the position of your mouse.
To reset the translation back to the origin without having to accurately position your mouse or change the value of the textboxes, just click "Reset Translation".
Translation scale changes how sensitive the image is to translation. It is most useful for when you want to make fine adjustments to the translation using your mouse, or want to significantly increase the translation.
You can also choose to translate the image in an ellipse, using the x and y translation values to control the size and shape of the ellipse. The translation speed slider can be used to control how quickly it moves in the elliptical path.
This effect has almost no effect on the audio and is mainly a visual effect. You might hear the effects of applying translation in an ellipse if you have an extremely high translation speed.
There are two volume sliders in osci-render. The first, "Master volume", is self-explanatory and controls the volume of the whole program. This is set to 0 by default if in the project select screen you tick the checkbox for "Start muted", and otherwise has a default value of 3.
The second volume slider modifies the sine waves of the non-main audio channels when playing back midi. This is used to control how much of these sine waves you want to see and hear, as they will distort the image.
2D Rotate speed controls how quickly the image rotates. When the value is at 0, no rotation is applied. At values larger than 0 it rotates anti-clockwise, and at values less than 0 it rotates clockwise.
You can hear a 'rotation' or panning audio effect when this is active and can clearly hear how quickly it is rotating.
3D perspective treats the image as a 3D object. It acts as if the image is projected onto a flat face and then that face is rotated around in 3D.
When the 3D perspective slider is at 0, no effect is applied. Between 0 and 1, the effect is partially applied, and at 1 it is fully enabled. You can get some very interesting effects when it's between 0 and 1 as it is halfway between being a 3D object and being a 2D image.
The 3D Distance slider controls how far away from the camera the 3D object is. If you increase the value, it will have the effect of making the image smaller. Since this is perspective projected from 3D coordinates into 2D, perspective distortion will appear. This also controls the value of the z
pre-defined variable when modifying the depth function.
The 3D rotation controls mirror those in the 3D .obj settings panel, including the fixed rotation axis icons to the right of the rotation axis sliders.
"Reset 3D Rotation" behaves as you would expect and resets all the rotation sliders back to 0.
Using Lua live-coding, you can also modify the function that controls the 3D position of every point drawn to the screen. This could allow you to change the depth of the image in a sine wave based on the x position of the point being drawn, or even create a sphere that has the image as a texture wrapped around it.
When clicking "Modify Depth Function", a text editor will appear allowing you to edit the Lua. There are three pre-defined variables: x
, y
, and z
, corresponding to the initial x position, y position, and z position (depth) of the image. The most simple script, return { x, y, z }
will apply no effect and return the same position and depth as default.
Some example depth functions in Lua:
-- Vary the depth of the image based on the x position
return {
-- x-position
x,
-- y-position
y,
-- z-position
z + 0.1 * math.sin(10 * x),
}
y = 0.4 * y
-- Equirectangular projection to wrap the image onto a sphere
return {
-- x-position
math.sin(math.pi * x) * math.cos(math.pi * y),
-- y-position
math.sin(math.pi * -y),
-- z-position
z + math.cos(math.pi * x) * math.cos(math.pi * y),
}
Trace max/min control how much of the image is currently being drawn. The value of trace max controls the proportion of the image that is drawn starting from the start of the image draw path and ending at the value of trace max as a proportion of the entire draw path. Trace min is slightly different since it starts at the end of the image and ends at the value of trace min as a proportion of the draw path in reverse.
This means that the only difference between trace max and trace min is the direction that the trace effect is applied.
The frequency slider controls how quickly the image is drawn, which in turn controls the frequency of the audio. A target frequency of 400Hz, for example, would draw the image 400 times per second, and the loudest real frequency is usually some multiple of 400Hz. This is named "Target frequency" as it is not necessarily the actual frequency you will hear. Any audio effects applied will have an impact on the current frequency, meaning the L/R frequencies in the Main settings panel could be vastly different to the frequency specified on this slider.
The text editor is used to edit files in osci-render. While it is currently quite barebones, it provides syntax highlighting and other standard features of a text editor, including undo/redo, and find and replace. Any changes made to a file are immediately reflected in the audio/visuals.
For more specific documentation on the general features of the text editor, it's best to look at CodeMirror's documentation as this is the library I am using.
Currently, there are two ways of opening the text editor. The most common way is by pressing the "Edit File" button in the Main settings panel, which allows you to modify the file you currently have open. The other place this is used is for the 3D perspective effect to define a custom program using Lua live-coding to transform the 3D coordinates given as an input.
You can only have one text editor window open at once, which means that any previous window will close if you open the text editor again. This currently causes a few issues since the same text editor is reused, such as undoing/redoing carrying over between different files.
todo
todo
Almost everything in osci-render that can be controlled using a slider can also be animated. Animation works by changing the slider values automatically over the slider's range. Therefore, changing the range of the slider will also change the range of the animation for that slider.
By default, every slider has a 'static' animation, which just means there is no animation at all and the effect's value is the same as the value displayed by the slider. To change the animation type, just use the dropdown to the right of most sliders in osci-render:
There are currently five animation types: Static, Seesaw, Linear, Forward, and Reverse. For all non-static animations, the speed of the animation is controlled with the same slider that controls the value of the effect. When the slider is all the way to the left, the animation has a speed of 0 and will be paused. As the slider moves to the right, the speed of the animation increases.
Below are details of each non-static animation type:
The Seesaw animation type moves more quickly depending on how far away the current value of the effect is from the minimum and maximum values. This has the effect of moving very slowly at the start, and then quickly accelerating to the mid-point, where it will quickly slow down again at the end.
Once it reaches the end, the direction of the animation is reversed and it returns back to the original position.
The Linear animation type has a constant speed throughout the animation from minimum to maximum effect value, and then back to the minimum. This makes the animation abruptly change direction when the effect's value reaches the maximum.
Forward is the same as Linear in that the speed is constant, however, it does not change direction and instead increases from the minimum effect value to the maximum and then instantly snaps back to the minimum afterwards.
Reverse is the same as Forward, except it moves in the opposite direction. It starts at the maximum effect value and decreases to the minimum before it snaps back to the maximum.
Osci-render has a Blender plugin that allows you to visualise a Blender scene in osci-render using Grease Pencil Line Art.
This video explains how to install and use osci-render with Blender, with an overview of the process below:
- Download the latest Blender add-on from Releases named osci-render-blender-addon.zip
- Install and enable the add-on in Blender
- "osci-render settings" menu will now appear under "Render Properties"
- Open osci-render
- Click "Connect to osci-render" in Blender
- If the text next to "Choose File" in the Main settings panel changes to "Rendering from external input" you have successfully connected
- Add a camera to the scene in Blender (if there isn't one already)
- Add a Scene Line Art object to the scene
- Press Shift+A and navigate to Grease Pencil > Scene Line Art
- Go to "Modifier Properties" of the newly created Line Art object
- Click "Bake Line Art" under the the "Bake" settings to generate line art for the current animation/scene/camera
- You should now see the scene on your oscilloscope!
todo