Hey! Very nice session! Really enjoyable and educational! Thanks! 😄 Some comments: - To get color from integer, raylib provides: `Color GetColor(unsigned int hexValue)` - In raylib all functions that allocate memory start with Load*() and have an Unload*() equivalent - Moving data from GPU memory to CPU memory (glReadPixels()) is always extremely slow >_< - I always build raylib with my projects, I usually adjust build parameters (the ones in config.h) despite with LTO it is not really needed... - Wave is for "audio frames" the same than Image for "pixels", "audio frames" and "pixels" have a number of channels and a size for each channel - raylib provides TextFormat() that works like sprintf(), returning a static string formated, very handy for things like DrawText(TextFormat("FPS: %i", GetFPS()), 10, 10, 20, GREEN);
Hey! Thank you for making raylib btw! I may look a bit grumpy on my sessions. But this is because I'm in a working mode. :D Raylib saved me a lot of time.
I really agree with what you said about passion in this industry, I dropped out of uni and during the first year of my current job, I learned two languages and how to write big code bases using them, I learnt how to setup devops pipelines and implement IaC. Now it's become obvious that no one except me cares whether anything is done well or properly. They are killing off the two deploy clusters I set up because they don't want to learn Linux, so the full logging, tracing and metrics system I set up is being replaced with Windows Event Log xD. I know I need to leave and find a placee where I can be with passionate people, I'm just starting to worry whether I'm going to be as passionate as I was when I started in Grade 6😂
I feel that pain of wondering whether anything you do makes a difference. You set up a system that works well, and they replace it with garbage because no one can be assed to learn how to use it, even with a full manual that took hours and hours of work to write. And it's usually with something Windows based too that doesn't even function half as well or have all the features and requires buying a subscription or a completely new piece of software each year. UGH!
If you want real passion around you, go back to Uni and keep studying until you have seven different PhDs or something. Like Tsoding said, business kills passion. Back in College, I was surrounded by crazy passionate people talking crazy stuff like Tsoding does and I felt "normal" with my own crazy ideas. In my jobs, I feel depressed because I rarely can go above discussing class names. People nowadays get dazzled how I know Haskell or how I code using only VIM. My own passion stays alive with side-projects. It is now self-sustained. The joy of making my own dreams real is something a company will never provide me.
@@ecosta I also code solely in Vim and it seems to boggle everyone I talk to. Seems like these days, nearly everyone uses the spyware known as VSCode. And you're so right about corporate coding. If you want passion, either avoid major corporations or do a lot of side projects.
Huh, I always saw ffmpeg as some sort of blackbox utility that only the oldest of elders knew the magical sequences to cast its spell properly... But your explanation makes a lot of sense! Now I too can cast ffmpeg >:D
Some time ago, when I wrote some code to generate frames and pipe them into FFMPEG, I thought: "meh, this is crazy". Now I feel so normal since there are clever people doing something similar... Thanks for the great content!
5:27 you just have to dig I've got a job where I'm free to do things however I like (luckily, I didn't have to dig much). Having to solve real world problems is much more satisfying because you're fulfilling a purpose and have actual constraints and users
Great job as always! Would be awesome to see you take a shot at building a concurrent web server in C, or maybe sth like reimplementing Golang's 'net' or 'net/http' module in C
Unexpected and enjoyable discussion about the passion-quenching effects of working in corporate programming jobs. Definitely been there and got burnt a few times.
It doesn't have to be an array btw, the following works too: *(Color*)&(uint32_t){0xFFFF7FFF} *(uint32_t*)&(Color){.r=255, .g=127, .b=255, .a=255} You can kinda do that with anything, like here is how to print the current time with libc's time.h in a single line: printf("%s", ctime(&(time_t){time(NULL)})); coumpound literals are a c99 feature and they're great :)
@@xhivo97 I know the second one is UB, clang even warns with -Wcast-align as Color is 1 byte aligned and uint32_t is 4 bytes aligned. But I'm not sure about the first one, maybe ¯\_(ツ)_/¯ I looked up the c99 standard to make sure and yeah, section 6.3.2.3.7 says: A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. The third one is good tho.
@@xhivo97 I think not, because it's like typing strings in quotes instead of allocating some static variable and filling it up byte by byte. The value is there, it just must be stored somewhere. My guess is it works just like string literals, storing value in data section.
I just looked it up and as far as I can tell, if the resulting pointer is correctly aligned it's OK to do otherwise it's undefined behavior. No idea how alignment works and how portable this is though so I would look into that and try to make sure it's going to work on all machines. @@rogo7330
@@rogo7330 good thinking, I actually didn't know where struct literals were stored, so I just tested it with gcc and clang. Turns out compound literals are stored on the stack, right next to variables. Color color = {.r=255, .g=127, .b=255, .a=255}; Color *color_p = (Color*)&(uint32_t){0xFFFF7FFF}; printf("%p %p %p ", &color, color_p, (Color*)&(uint32_t){0xFFFF7FFF}); // 00000077549DFE40 (we know color is stored on the stack, it's a variable) // 00000077549DFE34 (12 bytes down, 4 for the Color literal, 8 for color_ptr) // 00000077549DFE30 (4 bytes down for the Color literal) turns out I could just have read the standard, in section 6.5.2.5.6, it says: If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block. I tested the 'outside the body of a function' version of compound literals too: Color g_color = {.r=255, .g=127, .b=255, .a=255}; Color *g_color_p = (Color*)&(uint32_t){0xFFFF7FFF}; int main() { printf("%p %p ", &g_color, g_color_p); } // 00007FF765AB4000 // 00007FF765AB4004 they are right next to one another! damn I love c :)
The sample at 1:30 is obviously epic but it's frustrating to me that when the drums kick in you don't get a much bigger impact on the visualization. I guess that makes sense since (I'm guessing) drums are kind of like white noise, so adding in drums just gives you a slight increase to every frequency, rather than a dramatic increase to a few frequencies.
Yeah, it is generally very difficult to visualize chiptune in a meaningful way using FFT. Simply by the nature of chiptune. You need to do something interesting with the original notes the sound was generated from.
30:00 I would use an union to do that, it's far more clear what it's doing when you do: union { Color color; uint32_t abgr; } convert; convert.abgr = 0xFF181818; ClearBackground(convert.color);
Indeed, this is casting done right. But I think C programmers love single line shortcuts. I still assign in conditional expressions just to avoid an extra line of code.😁
Hi Alexey, I found this strange Icon on my phone with an X and opened it and it showed me something which looked like a retweet of you tweeting about musializer… My goto 3D Framework unfortunately does not have very good support for audio yet (not possible to access audio data while playing a Song) and I never had used Raylib before but I thought I would just have a look at the website. Next thing I know I made a Raylib hello world from C# project (since I am too lazy to learn C). I then started to port musializer to C#. Was not expecting it to work out but surprisingly it did after a day so that I am having fun with it playing random music and looking at the visualization. The render to video part is still missing though. Thanks for the cool project!
27:06 damn! I had no idea you could do such a thing. I was thinking you'd have to delve into bit shifting to get all the components and build a color struct.
curious if it's possible to have the rendering not be bound by the music's playtime, so you could potentially render faster no matter how long the track is, since it's just simulated anyways.
I love your way of swift coding in C++ Can you please let me know how to render ffmpeg preview on custom window like PictureBox of Form with hwnd ? I need to capture on file and show preview on my application window instead of ffplay. By the way I wanted on the command line.
Hi and thanks for the great video, very entertaining and a cool little project. Maybe you could implement Hardware/GPU Encoding with the H264 NVIDIA NVENC (`-c:v h264_nvenc`) or for AMD (`-c:v h264_amf` ? ). This could significantly speed up the encoding process. Looking forward to more content like this! Great stuff 👍
Dude, seriously, lets be friends. I code daily (lately tho brains been a pile of mashed potatoes lol), and atm I'm writing an AI system from the ground up without "traditional" methods (e.g weights / biases) or any guides as a part of a challenge; I need to write any required libs myself :) It's a lot of fun, and I encourage you to do something similar, you'd be surprised how much you might enjoy it =D
Why the height of bars on left side is always smaller than the center and that of the right side? Its kinda looks right skewed. Can you fix that in your upcoming sessions pls?
There is nothing to fix here. This is how Chiptune looks like because it uses square waves that have this natural ramp due to a lot of harmonics. Here is how for example the beginning of the songs "Greetings" by PilotRedSun looks like i.imgur.com/q2DwJJB.png
Just wondering have you ever tried to fix some type of compatibility issue in ffmpeg external libraries presented in vcpkg ? might be a silly question so dont judge to hard... ahhaha
26:10 Aren't "union" in C designed for this purpose? Two data structures occupying the same memory? You can define union of Color and rgba, to make it clean! Or may be I am missing some dependency of olive.c.
@@anon_y_moussecan you provide a bit a more context please? To me it is not clear why this is a problem if they are both 4 consecutive bytes in memory.
Ok I think I kind of got it. You can't just cast them because to C those two are completely different types even if there representation in memory is the same. According to stack overflow the process tsoding used to convert the types is called type punning which is basically the reinterpretation of a block of memory as a different type. You can achieve the same by using a union. Using a union is a bit safer but both approaches may cause portability problems due to different endianess.
@@danielschmitt5750 The endianness issue is why it's not portable, though in practice I've rarely encountered an actual big endian platform even using a lot of ARM processors. Ideally, you would put the conversion in a macro so you could control how it's done as per the platform you're compiling for, and the union method would be safer, but not nearly as convenient or pretty.
twitter definitely seems like a company that views legacy code as immutable. though, i can see that being an adverse effect of high turnover that their new ceo certainly is not helping
30:37 I done something like that previously in my statusbar for dwm in config.h file (if you know, you know) for array of arrays of shorts. But when I looked at it once again I realised that it kills my braincells and got rid of it. Instead I completly rewrote config logic and put shorts into structures with growing array at the end.
You can actually specify with most of the options. Like say you're selecting the audio codec, you can use -c:a "some codec" or you could use -acodec "some codec".
@@anon_y_mousseno, by muxer options I mean stuff like `-movflags +faststart` in mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer it's unclear does `-movflags +faststart` belong to video encoder or audio encoder or muxer if you don't know the parameter
@@RandomGeometryDashStuff Since it affects the output, that's where it belongs. Although, as far as I'm aware it's position independent on the command line.
regarding your comments about the lack of passionate and competent people blowing up in our face - it's already happening. Look around you at the software people use on a daily basis. Every year it gets slower, less stable, and more buggy. Poor performance and poor usability are normalized, while the industry sits on its laurels, oblivious to the damage being done to the software ecosystem.
Hey! Very nice session! Really enjoyable and educational! Thanks! 😄
Some comments:
- To get color from integer, raylib provides: `Color GetColor(unsigned int hexValue)`
- In raylib all functions that allocate memory start with Load*() and have an Unload*() equivalent
- Moving data from GPU memory to CPU memory (glReadPixels()) is always extremely slow >_<
- I always build raylib with my projects, I usually adjust build parameters (the ones in config.h) despite with LTO it is not really needed...
- Wave is for "audio frames" the same than Image for "pixels", "audio frames" and "pixels" have a number of channels and a size for each channel
- raylib provides TextFormat() that works like sprintf(), returning a static string formated, very handy for things like DrawText(TextFormat("FPS: %i", GetFPS()), 10, 10, 20, GREEN);
Hey! Thank you for making raylib btw! I may look a bit grumpy on my sessions. But this is because I'm in a working mode. :D Raylib saved me a lot of time.
@@TsodingDaily Hahaha... nah! Sessions are great! You are doing really interesting projects and very well explained! 😄
Alexey, great work! Your recreational sessions are super inspiring. Thank you so much!
There are two kinds of people "We cant malloc two times in a single frame" and then every game dev currently "haha memory goes brrrrr"
my 32 GB RAM don't care about malloc calls
My 64 GB RAM don’t care about malloc calls
My 8 GB RAM does :(
my 512kb nokia does care about the smallest memory optimizations ;(
I really agree with what you said about passion in this industry, I dropped out of uni and during the first year of my current job, I learned two languages and how to write big code bases using them, I learnt how to setup devops pipelines and implement IaC.
Now it's become obvious that no one except me cares whether anything is done well or properly. They are killing off the two deploy clusters I set up because they don't want to learn Linux, so the full logging, tracing and metrics system I set up is being replaced with Windows Event Log xD.
I know I need to leave and find a placee where I can be with passionate people, I'm just starting to worry whether I'm going to be as passionate as I was when I started in Grade 6😂
I feel that pain of wondering whether anything you do makes a difference. You set up a system that works well, and they replace it with garbage because no one can be assed to learn how to use it, even with a full manual that took hours and hours of work to write. And it's usually with something Windows based too that doesn't even function half as well or have all the features and requires buying a subscription or a completely new piece of software each year. UGH!
If you want real passion around you, go back to Uni and keep studying until you have seven different PhDs or something. Like Tsoding said, business kills passion. Back in College, I was surrounded by crazy passionate people talking crazy stuff like Tsoding does and I felt "normal" with my own crazy ideas. In my jobs, I feel depressed because I rarely can go above discussing class names. People nowadays get dazzled how I know Haskell or how I code using only VIM.
My own passion stays alive with side-projects. It is now self-sustained. The joy of making my own dreams real is something a company will never provide me.
@@ecosta I also code solely in Vim and it seems to boggle everyone I talk to. Seems like these days, nearly everyone uses the spyware known as VSCode. And you're so right about corporate coding. If you want passion, either avoid major corporations or do a lot of side projects.
@@ecosta Awful advice. University kills passion like nothing else.
@@pyrus2814 I guess it depends on Uni. Still better than trying to have fun in companies.
I would pay so much money to learn from someone as exceptional as you man
Well isn't it amazing that he gives it all here for free!
What do you want to learn ?
Huh, I always saw ffmpeg as some sort of blackbox utility that only the oldest of elders knew the magical sequences to cast its spell properly... But your explanation makes a lot of sense!
Now I too can cast ffmpeg >:D
I adore ffmpreg
Some time ago, when I wrote some code to generate frames and pipe them into FFMPEG, I thought: "meh, this is crazy". Now I feel so normal since there are clever people doing something similar... Thanks for the great content!
5:27 you just have to dig
I've got a job where I'm free to do things however I like (luckily, I didn't have to dig much). Having to solve real world problems is much more satisfying because you're fulfilling a purpose and have actual constraints and users
Great job as always!
Would be awesome to see you take a shot at building a concurrent web server in C, or maybe sth like reimplementing Golang's 'net' or 'net/http' module in C
Unexpected and enjoyable discussion about the passion-quenching effects of working in corporate programming jobs. Definitely been there and got burnt a few times.
It doesn't have to be an array btw, the following works too:
*(Color*)&(uint32_t){0xFFFF7FFF}
*(uint32_t*)&(Color){.r=255, .g=127, .b=255, .a=255}
You can kinda do that with anything, like here is how to print the current time with libc's time.h in a single line:
printf("%s", ctime(&(time_t){time(NULL)}));
coumpound literals are a c99 feature and they're great :)
Isn't that undefined behavior?
@@xhivo97 I know the second one is UB, clang even warns with -Wcast-align as Color is 1 byte aligned and uint32_t is 4 bytes aligned. But I'm not sure about the first one, maybe ¯\_(ツ)_/¯
I looked up the c99 standard to make sure and yeah, section 6.3.2.3.7 says:
A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.
The third one is good tho.
@@xhivo97 I think not, because it's like typing strings in quotes instead of allocating some static variable and filling it up byte by byte. The value is there, it just must be stored somewhere. My guess is it works just like string literals, storing value in data section.
I just looked it up and as far as I can tell, if the resulting pointer is correctly aligned it's OK to do otherwise it's undefined behavior. No idea how alignment works and how portable this is though so I would look into that and try to make sure it's going to work on all machines. @@rogo7330
@@rogo7330 good thinking, I actually didn't know where struct literals were stored, so I just tested it with gcc and clang. Turns out compound literals are stored on the stack, right next to variables.
Color color = {.r=255, .g=127, .b=255, .a=255};
Color *color_p = (Color*)&(uint32_t){0xFFFF7FFF};
printf("%p
%p
%p
", &color, color_p, (Color*)&(uint32_t){0xFFFF7FFF});
// 00000077549DFE40 (we know color is stored on the stack, it's a variable)
// 00000077549DFE34 (12 bytes down, 4 for the Color literal, 8 for color_ptr)
// 00000077549DFE30 (4 bytes down for the Color literal)
turns out I could just have read the standard, in section 6.5.2.5.6, it says:
If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.
I tested the 'outside the body of a function' version of compound literals too:
Color g_color = {.r=255, .g=127, .b=255, .a=255};
Color *g_color_p = (Color*)&(uint32_t){0xFFFF7FFF};
int main() { printf("%p
%p
", &g_color, g_color_p); }
// 00007FF765AB4000
// 00007FF765AB4004
they are right next to one another!
damn I love c :)
I love the dabs at the very beginning
The sample at 1:30 is obviously epic but it's frustrating to me that when the drums kick in you don't get a much bigger impact on the visualization. I guess that makes sense since (I'm guessing) drums are kind of like white noise, so adding in drums just gives you a slight increase to every frequency, rather than a dramatic increase to a few frequencies.
Yeah, it is generally very difficult to visualize chiptune in a meaningful way using FFT. Simply by the nature of chiptune. You need to do something interesting with the original notes the sound was generated from.
Consider doing a wavelet transform instead. There should be one that project out sawtooth and square waves quite well.
Did you know that Tsioding is #13 most viewed twitch programmist?
no.
i always thought he was super niche, but i see him popping up everywhere nowadays
30:00 I would use an union to do that, it's far more clear what it's doing when you do:
union {
Color color;
uint32_t abgr;
} convert;
convert.abgr = 0xFF181818;
ClearBackground(convert.color);
Indeed, this is casting done right. But I think C programmers love single line shortcuts. I still assign in conditional expressions just to avoid an extra line of code.😁
Hi Alexey, I found this strange Icon on my phone with an X and opened it and it showed me something which looked like a retweet of you tweeting about musializer… My goto 3D Framework unfortunately does not have very good support for audio yet (not possible to access audio data while playing a Song) and I never had used Raylib before but I thought I would just have a look at the website. Next thing I know I made a Raylib hello world from C# project (since I am too lazy to learn C). I then started to port musializer to C#. Was not expecting it to work out but surprisingly it did after a day so that I am having fun with it playing random music and looking at the visualization. The render to video part is still missing though. Thanks for the cool project!
lolz "can your rust do that?" Thanks for the great videos as always :)
27:06 damn! I had no idea you could do such a thing. I was thinking you'd have to delve into bit shifting to get all the components and build a color struct.
Bro is so smart that codes videos with c
These vids keep me going 😊
curious if it's possible to have the rendering not be bound by the music's playtime, so you could potentially render faster no matter how long the track is, since it's just simulated anyways.
Is Raylib more friendly for recreational programming then SDL or is it just latest fixation?
much simpler
Yeah, much easier.
IMO, raylib has a simpler and easier to use api.
I love your way of swift coding in C++
Can you please let me know how to render ffmpeg preview on custom window like PictureBox of Form with hwnd ?
I need to capture on file and show preview on my application window instead of ffplay.
By the way I wanted on the command line.
Ooh if this were to work with alsa/pulseaudio, then I would use it as a wallpaper!
Hi and thanks for the great video, very entertaining and a cool little project. Maybe you could implement Hardware/GPU Encoding with the H264 NVIDIA NVENC (`-c:v h264_nvenc`) or for AMD (`-c:v h264_amf` ? ). This could significantly speed up the encoding process. Looking forward to more content like this! Great stuff 👍
Dude, seriously, lets be friends.
I code daily (lately tho brains been a pile of mashed potatoes lol), and atm I'm writing an AI system from the ground up without "traditional" methods (e.g weights / biases) or any guides as a part of a challenge; I need to write any required libs myself :)
It's a lot of fun, and I encourage you to do something similar, you'd be surprised how much you might enjoy it =D
Very cool!
Great video.
We can do DrawCircle(x, y, r, (Color){0xFF, 0x18, 0x18, 0x18}); Just split up the integer.
01:09:02 same number of chars but isn't uint64 max 2**64-1?
Amazing your knowledge....
Why the height of bars on left side is always smaller than the center and that of the right side? Its kinda looks right skewed. Can you fix that in your upcoming sessions pls?
There is nothing to fix here. This is how Chiptune looks like because it uses square waves that have this natural ramp due to a lot of harmonics.
Here is how for example the beginning of the songs "Greetings" by PilotRedSun looks like i.imgur.com/q2DwJJB.png
I understand 10% of this shit I'll go and get better at C then come back
Just wondering have you ever tried to fix some type of compatibility issue in ffmpeg external libraries presented in vcpkg ? might be a silly question so dont judge to hard... ahhaha
26:10 Aren't "union" in C designed for this purpose? Two data structures occupying the same memory? You can define union of Color and rgba, to make it clean!
Or may be I am missing some dependency of olive.c.
❤
Passion
Can someone explain to me why we not just can cast uint32_t to Color if it is the same in memory anyway?
I am wondering the same thing
Because it's a structured type.
@@anon_y_moussecan you provide a bit a more context please? To me it is not clear why this is a problem if they are both 4 consecutive bytes in memory.
Ok I think I kind of got it. You can't just cast them because to C those two are completely different types even if there representation in memory is the same. According to stack overflow the process tsoding used to convert the types is called type punning which is basically the reinterpretation of a block of memory as a different type. You can achieve the same by using a union. Using a union is a bit safer but both approaches may cause portability problems due to different endianess.
@@danielschmitt5750 The endianness issue is why it's not portable, though in practice I've rarely encountered an actual big endian platform even using a lot of ARM processors. Ideally, you would put the conversion in a macro so you could control how it's done as per the platform you're compiling for, and the union method would be safer, but not nearly as convenient or pretty.
01:11:25 how about let user edit ffmpeg arguments manually before starting rendering?
How would it look if reduce the radius to the peak? With this thought the second video :). Thank you.
twitter definitely seems like a company that views legacy code as immutable. though, i can see that being an adverse effect of high turnover that their new ceo certainly is not helping
You have to add coogle into your ide as a lsp/ copilot tool
the word "zozi" looks like 2021
well, I think C11 also allows you to do this: void foo(int *x); foo(&(int){5});
zozin what desktop gui do u use? really interesting
It’s i3wm
30:37 I done something like that previously in my statusbar for dwm in config.h file (if you know, you know) for array of arrays of shorts. But when I looked at it once again I realised that it kills my braincells and got rid of it. Instead I completly rewrote config logic and put shorts into structures with growing array at the end.
12:27 the real confusing part is in [output_file_options]: does flag configure video encoder or audio encoder or muxer?
You can actually specify with most of the options. Like say you're selecting the audio codec, you can use -c:a "some codec" or you could use -acodec "some codec".
@@anon_y_mousseyes for video it's `-option:v value`, for audio it's `-option:a value`, but there is *no* `-option:m value` for muxer
@@RandomGeometryDashStuff I'd guess that's because of -map and the ability to select the stream you want affected with each setting.
@@anon_y_mousseno, by muxer options I mean stuff like `-movflags +faststart` in mov/mp4/tgp/psp/tg2/ipod/ismv/f4v muxer
it's unclear does `-movflags +faststart` belong to video encoder or audio encoder or muxer if you don't know the parameter
@@RandomGeometryDashStuff Since it affects the output, that's where it belongs. Although, as far as I'm aware it's position independent on the command line.
Hey man, do you actually work for a company? How do you have so much time
Can you make a file system...in rust?
1:11:19 I was like, how does that string function know where the print data is? so when he builds "Oh, I need the buffer" LOL
mental dmg indeed.
n + 1 :th.
me recuerda a manim de 3blue1brown
regarding your comments about the lack of passionate and competent people blowing up in our face - it's already happening. Look around you at the software people use on a daily basis. Every year it gets slower, less stable, and more buggy. Poor performance and poor usability are normalized, while the industry sits on its laurels, oblivious to the damage being done to the software ecosystem.
Duh
First
Third
Second
Get a job ❤
He has one, its called being a content creator
Do you have any idea how much a job in software engineering makes? Looks like you're the one who needs to get a job.
He's doing his job quite well sir.
Awesome 🎉