Posts: 714
Threads: 36
Joined: May 2022
Reputation:
13
Quote:@grymmjack - I loved VB6 back in the day. I made some really fun stuff with it.
Did you see InformPE? Check it out! @a740g and @fellipe (I'm sorry I don't know if he's a user here, and I have no desire to look for the name because: lazy). made it.
I tried InForm last year but something went wrong; it all hung up after a short time. Something got in the way. I then reinstalled QB64 without InForm.
But, it's a great job. I haven't tried QBJS yet. I am are no longer as not quite as adventurous as I used to be. It is really just a hobby now to get my mind off things.
Do you know this page here - A really good (old)site?: Fravia Searchlores
Unfortunately: Fravia - R.I.P.
I did not know Cracked. Mad Magazine was also here, but I never read it. But I read this one (I found it in a library back then). Can't find the link right now.
Freak Brothers.
Posts: 714
Threads: 36
Joined: May 2022
Reputation:
13
Posts: 304
Threads: 19
Joined: Nov 2022
Reputation:
17
(06-17-2023, 03:12 PM)doppler Wrote: (06-17-2023, 02:09 PM)grymmjack Wrote: I'm super excited about this stuff! Thanks for the sound demo. It's giving me some ideas for revisiting old sound play code I wrote (in programs). NP sir. It's a lot of fun to see what we can make.
I really love those old PC speaker sound effects. From the likes of Duke Nukem 1, Commander Keen, etc.
Pretty awesome what they were able to achieve you know? Just square waves, frequency, duration. Nothing more.
Posts: 1,510
Threads: 53
Joined: Jul 2022
Reputation:
47
06-18-2023, 12:00 AM
(This post was last modified: 06-18-2023, 01:15 AM by mnrvovrfc.)
https://github.com/zserge/1bitr
Had a lot of fun with this for at least a week with a Lua script I wrote doing 20-minute muzak LOL. Even recorded it to wave and imported it into Audacity creating a stereo pair and applied reverb. Was very bored that day.
Code: (Select All) -- by mnrvovrfc, verified 17-Jun-2023
function table_create(atable)
function local_table_copy(t)
local tret
function local_copy(t)
local tret = { }
for i = 1, #t do
tret[i] = t[i]
end
for k, v in pairs(t) do
if type(v) == "table" then
tret[k] = local_copy(v)
elseif type(k) ~= "number" then
tret[k] = v
end
end
return tret
end
tret = local_copy(t)
return tret
end
local tret = {
insert = function (s, ...)
local rest = { ... }
if rest == nil or #rest == 0 then return end
local lrest = #rest
for i = 1, lrest do
table.insert(s, rest[i])
end
end,
first = function (s, t)
if t == nil then return end
table.insert(s, 1, t)
end,
enter = function (s, t)
if type(t) ~= "table" or #t == 0 then return end
local ts = local_table_copy(t)
table.insert(s, ts)
end,
concat = function (s, delim, pfrom, pto)
return table.concat(s, delim, pfrom, pto)
end,
copy = function (s, ts, append)
if type(ts) ~= "table" then return end
if next(ts) == nil then return end
if append == nil then s:delete() end
local n = #ts
for i = 1, n do
table.insert(s, ts[i])
end
end,
remove = function (s, spos)
table.remove(s, spos)
end,
delete = function (s)
local n = #s
while n > 0 do
table.remove(s)
n = n - 1
end
end,
clear = function (s)
s:delete()
end,
is_empty = function (s)
-- not a good way, but the alternative is to search all elements for one with numeric index
-- the assumption is that if table_create() is used to create a table then
-- "insert" method would be used to add elements, like an array in BASIC
return (#s == 0)
end,
find = function (s, aval)
if aval == nil then return nil end
if type(aval) ~= "number" and type(aval) ~= "string" then return nil end
if type(aval) == "number" then aval = tostring(aval) end
local laval = string.lower(aval)
local akey, ve
for kk, vv in pairs(s) do
if type(vv) == "number" then ve = tostring(vv) end
if type(vv) == "string" then ve = string.lower(vv) end
if ve == laval then
akey = kk
break
end
end
return akey
end
}
if type(atable) == "table" and next(atable) ~= nil then
local t = tret
tret = local_table_copy(atable)
if not tret.insert then
tret.insert = t.insert
tret.clear = t.clear
tret.concat = t.concat
tret.copy = t.copy
tret.delete = t.delete
tret.enter = t.enter
tret.find = t.find
tret.first = t.first
tret.is_empty = t.is_empty
tret.remove = t.remove
end
end
return tret
end
function sformat(aformat, arg1, ...)
if arg1 == nil then
return aformat
end
return string.format(aformat, arg1, ...)
end
function ran(a, b)
if type(a) ~= "number" then return nil end
if math.floor(a) == math.floor(b) then return a end
if a < 0 and b < 0 then
a = a * -1
b = b * -1
if a > b then a, b = b, a end
return math.random(a, b) * -1
end
if a > b then a, b = b, a end
if a < 0 or b < 0 then
local x = a * -1
if b < 0 then x = b * -1 end
return math.random(a + x, b + x) - x
end
return math.random(a, b)
end
function choicet(tbl)
if type(tbl) ~= "table" then
return ""
end
local x
local numele = #tbl
if numele == 0 then return "" end
if numele == 1 then return tbl[1] end
repeat
x = math.random(1, numele)
until x ~= choicetprev
choicetprev = x
return tbl[x]
end
function findstr(txt, lookfor)
return string.find(txt, lookfor, 1, true)
end
-- main program
tn = table_create()
tc = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-" }
for j = 3, 7 do
for i = 1, 12 do
tn:insert(sformat("%s%d", tc[i], j))
end
end
tc = nil
nprog = {
{ 3, 4, 3, 4 },
{ 3, 4, 3, 5 },
{ 3, 4, 5, 6 },
{ 3, 5, 5, 6 },
{ 5, 6, 5, 7 },
{ 5, 5, 5, 7 },
{ 4, 5, 5, 5 },
{ 4, 5, 5, 7 },
{ 4, 7, 5, 5 },
{ 4, 7, 5, 7 },
{ 3, 7, 5, 5 },
{ 3, 7, 5, 7 },
{ 3, 7, 7, 6 },
{ 3, 7, 7, 7 },
{ 4, 7, 7, 6 },
{ 4, 7, 5, 5 },
{ 4, 5, 7, 7 },
{ 5, 5, 7, 7 },
{ 6, 7, 7, 7 },
{ 6, 5, 5, 5 },
{ 6, 3, 7, 5 },
{ 4, 7, 3, 5 },
{ 3, 7, 4, 5 },
{ 7, 7, 7, 7 }
}
lnprog = #nprog
popsong = {
{ 4, 4, 2, 4, 4, 2, 2, 2, 4, 4, 2, 2, 2, 4, 4, 2, 4, 4, 2, 2, 2, 1 },
{ 4, 4, 2, 4, 4, 2, 2, 2, 8, 8, 4, 2, 2, 2, 4, 4, 2, 4, 8, 8, 2, 2, 2, 1 },
{ 4, 4, 8, 8, 8, 8, 4, 4, 2, 8, 8, 8, 8, 2, 8, 8, 4, 2, 8, 8, 8, 8, 2, 4, 4, 2, 8, 8, 4, 8, 8, 8, 8, 2, 2, 1 },
{ 2, 8, 8, 2, 4, 8, 8, 8, 8, 2, 4, 2, 4, 8, 8, 2, 8, 8, 8, 8, 2, 4, 4, 4, 8, 8, 8, 8, 4, 2, 4, 8, 8, 8, 8, 1 },
{ 4, 4, 2, 8, 8, 8, 8, 4, 2, 2, 8, 8, 8, 1 },
{ 4, 2, 4, 2, 2, 8, 8, 8, 8, 2, 2 },
{ 2, 8, 8, 2, 4, 2, 2, 2, 8, 8, 2, 4, 2, 4, 4 },
{ 4, 2, 4, 8, 8, 8, 8, 4, 2, 2, 2 },
{ 8, 8, 8, 8, 2, 8, 8, 8, 8, 4, 4, 4, 4, 4 },
{ 8, 8, 2, 8, 8, 8, 8, 2, 8, 8, 4, 4, 4, 4 },
{ 2, 8, 8, 2, 4, 2, 2, 2, 8, 8, 2, 4, 2, 8, 3 },
{ 8, 8, 2, 8, 8, 4, 2, 8, 8, 8, 8, 4, 8, 3 },
{ 0 }
}
lpopsong = #popsong
popline = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6 }
raise = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2 }
for o = 10, 59 do
repeat
goahead = true
u = ran(64, 125) * 2
t = table_create{ u }
for i = 1, 3 do
t:insert(t[i] / 2)
end
for i = 1, #t do
sg = tostring(t[i])
if findstr(sg, '.') then
if not findstr(sg, ".0") then
-- print("Warning: dividing the note length doesn't produce a whole value.")
goahead = false
end
end
end
until goahead
notelen = { t[1], t[2], 0, t[3], 0, 0, 0, t[4] }
t = nil
notelen[3] = notelen[4] + notelen[8]
-- notelen[6] = notelen[8] + math.floor(notelen[8] / 2)
noat, nute = table_create(), table_create()
u = ran(1, 18)
uu = u
m = ran(3, 7)
t = choicet(nprog)
for i = 1, #t do
noat:insert(u)
if i == m then noat:insert(0) end
u = u + t[i]
end
noat:insert(u)
u = uu
m = ran(3, 7)
t = choicet(nprog)
for i = 1, #t do
nute:insert(u)
if i == m then nute:insert(0) end
u = u + t[i]
end
nute:insert(u)
fo = io.open(sformat(os.getenv("HOME") .. "/Documents/z1bitr/musak%02d", o - 9), "w")
if fo then fo:write("; 0\n") end
song = choicet(popsong)
if song[1] == 0 then
local t = { 4, 4, 8, 8, 2, 8, 8, 4, 4, 2, 8, 8, 8, 8, 2, 8, 8, 4, 2, 8, 8, 8, 8, 2, 4, 4, 2, 8, 8, 4, 8, 8, 8, 8, 2, 1 }
local l = #t
local w = ran(1, l)
local x = w - 1
local r = 0
local g = ran(2, 4)
local c = 1
local d
song = table_create()
repeat
if t[w] == 2 then
r = r + 1
if r == g then
song:insert(3, 8)
else
song:insert(t[w])
end
else
song:insert(t[w])
end
w = w + 1
if w > l then break end
c = c + 1
until c > l
if c <= l then
if x == 0 then
print("SOMETHING IS WRONG!")
os.exit()
end
if ran(1, 2) == 1 then
w = x
d = -1
else
w = 1
d = 1
end
repeat
if t[w] == 2 then
r = r + 1
if r == g then
song:insert(3, 8)
else
song:insert(t[w])
end
else
song:insert(t[w])
end
w = w + d
c = c + 1
until c > l
end
end
lsong = #song
pass = math.ceil(math.sqrt(o))
y = ran(1, pass)
for j = 1, pass do
kount = 1
newpopline = table_create()
for i = 1, lsong do
newpopline:insert(choicet(popline))
end
repeat
u = song[kount]
-- restrict the pause to the two shortest note lengths
trig = newpopline[kount]
if j == y then
if nute[trig] then
if u < 4 and nute[trig] == 0 then
trig = 1
end
else
trig = 1
end
else
if noat[trig] then
if u < 4 and noat[trig] == 0 then
trig = 1
end
else
trig = 1
end
end
-- the lowest two notes in the sequence never vary
if (j == y and trig > 2) then
w = choicet(raise)
if w == -1 then w = 3 end
elseif (trig > 3) or (trig == 3 and ran(1, 3) == 1) then
w = choicet(raise)
else
w = 0
end
if j == y then
if nute[trig] == 0 then
-- out-of-range on purpose so it's later considered a pause
v = 1e+6
else
v = nute[trig] + w
end
else
if noat[trig] == 0 then
v = 1e+6
else
v = noat[trig] + w
end
end
if v > #tn then
st = "---"
else
st = tn[v]
end
print(sformat("%s%c%02x", st, 32, notelen[u]))
if fo then
fo:write(sformat("%s%c%02x\n", st, 32, notelen[u]))
fo:write(sformat("%s%c%02x\n", st, 32, notelen[u]))
end
kount = kount + 1
until kount > lsong
end
if fo then fo:close() end
print("===")
end -- for o
ROFL doesn't sound enough like Color Computer playing through a budget television. It had to be the Color Computer 2 because the COCO3 did have "PLAY" which supported volume but could play one voice at a time with square wave.
This is an early version of the script I made, ended up making another one which created sets of three for one song, for left, center and right channels for stereo music. This script presented here requires Lua v5.4 or later. The line with "io.open()" statement could be changed easily to something that makes sense on Windows ("USERPROFILE" environment variable instead of "HOME"). Make sure "1bitr" is installed, and "z1bitr" directory (which is what I called the installation directory) exists inside "Documents" of your regular user's account before running this script.
Then feed one of the text files to the program like this:
Code: (Select All) $ ./1bitr < musak01
EDIT: Sorry for the lack of indentation, it seems this forum really wants CHR$(9) characters for it, it sucks.
Posts: 1,510
Threads: 53
Joined: Jul 2022
Reputation:
47
Here's that same Lua script as attachment so you could enjoy the indentation.
mnrvovrfc-noater-lua.zip (Size: 2.69 KB / Downloads: 62)
Posts: 1,510
Threads: 53
Joined: Jul 2022
Reputation:
47
I'm sorry for the off-topic (and wrong focused programming language). One concept that is not employed, but that I'm thinking about now is keeping track of song "snippets" into arrays such as:
Code: (Select All) songsnippet(1, 1) = "L8O4AO5C#"
songsnippet(1, 2) = "L4O3A"
songsnippet(2, 1) = "L16O4AFL8O5C#"
songsnippet(2, 2) = "L8O3FC#"
songsnippet(3, 1) = "L16O4FL8AL16O5C#"
songsnippet(3, 2) = "L4O3F"
and send them together for two-channel sound. (I purposely used PLAY strings expected by the Color Computer 3 in this example.) Also because I'm not very good with traditional musical concepts, especially scales I made a simple process in which a "lowest" note is selected, then four or five other notes are created from an array like this:
Code: (Select All) scale(1) = 4
scale(2) = 5
scale(3) = 3
scale(4) = 4
scale(5) = 3
basenote = 36: 'two octaves below "middle C"
notes(1) = basenote
for i = 1 to 5
basenote = basenote + scale(i)
notes(i + 1) = basenote
next
Then the musak is generated only selecting notes from "notes()" array as indicated in the above example. (In QB64 use "N" command for PLAY.) For each song, of course, the "scale()" array and "basenote" would be initialized differently. However, the Lua script only does one channel at a time. The "1bitr" has a multi-channel mode but I'm unwilling to study it. LOL click drums, I want something better than that after hearing enough chiptunes.
Posts: 2,700
Threads: 124
Joined: Apr 2022
Reputation:
134
06-18-2023, 02:39 PM
(This post was last modified: 06-18-2023, 02:40 PM by bplus.)
Quote:I'm sorry for the off-topic (and wrong focused programming language). One concept that is not employed, but that I'm thinking about now is keeping track of song "snippets" into arrays such as:
@mnrvovrfc I am sorry too, wading through all this off topic stuff.
Start a thread! then no one has to be sorry
b = b + ...
Posts: 1,510
Threads: 53
Joined: Jul 2022
Reputation:
47
In one of the best Arch Linux derrivatives going, called EndeavourOS, might also have to do this line so QB64PE is created successfully. Note no "dev" nor "devel" after the item names, which boggled me today. Everything else needed is already installed, eg. "g++", "alsa-lib".
Code: (Select All) $ sudo pacman -S glu libcurl-compat
|