[Solved] Help to get Sunvox module volume (maybe using json?)

All topics about ZGameEditor goes here.

Moderator: Moderators

Post Reply
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

[Solved] Help to get Sunvox module volume (maybe using json?)

Post by Ats »

Hello.
I found someone to make the music for my game. He’s excellent at composing, but not so good at naming the tracks and instrument modules...

Code: Select all

{
    "gc1": {
        "sunsynth": "gc1.sunsynth",
        "volume": 400,
        "transpose": 24
    },
    "cc1": {
        "sunsynth": "cc1.sunsynth",
        "volume": 310,
        "transpose": 16
    },
    "hh1": {
        "sunsynth": "hh1.sunsynth",
        "volume": 115,
        "transpose": 24
    },
    "cr1": {
        "sunsynth": "cr1.sunsynth",
        "volume": 310,
        "transpose": 2
    },
    "gt1": {
        "sunsynth": "gt1.sunsynth",
        "volume": 200,
        "transpose": -4
    },
    
    ...
}
Tracks and instruments have all the same 2 letters and the number 1 as a name. It’s a nightmare to read and debug...

So I’m programming a little ZGE app to read the SunVox file and get the module names, so I don't have to do it manually:

Code: Select all

void ListMusicModules()
{
  // Get the total number of modules
  int num_modules = sv_get_number_of_modules(0);

  // Loop through each module and print its name
  for (int i = 0; i < num_modules; i++) {
      string module_name = sv_get_module_name(0, i);
      trace("Module " + intToStr(i) + ": " + module_name);
  }
}
which returns:

Code: Select all

Module 0: Output
Module 1: 
Module 2: Amplifier
Module 3: Noise
Module 4: cr
Module 5: cc2
Module 6: syn2
Module 7: bass2
Module 8: gt2
Module 9: vib
Module 10: guit1                 
Module 11: pad
Module 12: Echo
Module 13: gc2
Module 14: 
Module 15: hh2
Module 16: syn1
Module 17: 
Module 18: 
Module 19: 
I realize now that it doesn’t even correspond to the JSON. It might not be the right version of the song... :?
Anyway, with the correct version of the song, the module names should correspond to the ones listed in the JSON.

So I was wondering if the JSON can be read by ZGE, so I can get the base volume for each module.

I wrote a function to convert those numbers to something that sv_send_event understands:

Code: Select all

/*
  Convert a linear volume (0?512) to SunVox hex format.
  Example: 242 -> '0x1E40'
*/
int GetSunvoxVolumeHex(int volume)
{
    if (volume < 0 || volume > 512)
    {
        trace("Volume must be between 0 and 512");
        return 0;
    }
    int sunvox_vol = volume * 0x4000 / 512;
    return sunvox_vol;
}
So if I shut down the volume of the bass (module 7+1) using:
sv_send_event(0, 1, 0, 0, 8, 0x0100, 0);

Then I can restore it to its original level afterward:
sv_send_event(0, 1, 0, 0, 8, 0x0100, GetSunvoxVolumeHex(bass_volume)); // bass volume from the JSON file


Unless there’s a simpler way to get the volume directly from the module, but I don’t think the SunVox wrapper provides that option.
Last edited by Ats on Mon Aug 18, 2025 2:43 pm, edited 2 times in total.
User avatar
Kjell
Posts: 1945
Joined: Sat Feb 23, 2008 11:15 pm

Re: Help with Sunvox volume and json

Post by Kjell »

Hi Ats,
Ats wrote: Mon Aug 18, 2025 1:35 pmI was wondering if the JSON can be read by ZGE, so I can get the base volume for each module.
There's no JSON parser built into ZGE ... and i don't think anyone has written a JSON ZLibrary either.

What are you're trying to do exactly? Can't you use sv_get_module_ctl_value to retrieve the volume of a module?

K
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Help with Sunvox volume and json

Post by Ats »

I wrote a program that reads a MIDI file, adds the SunSynth instrument to the tracks with the transposition and volume values listed in the JSON, and then saves it as a SunVox file. This works perfectly.

Now, in ZGE, I’m trying to get the base volume of each module. That’s why I was wondering if I could read the JSON, since there’s no such thing as sv_get_module_ctl_value in Rado1’s ZGE SunVox wrapper.

Code: Select all

/*
  Adapter to the SunVox Library.
  http://www.warmplace.ru/soft/sunvox

  Created by Rado1(c)2012-2013

  Download the library from http://www.warmplace.ru/soft/sunvox/sunvox_dll.zip
  More info: http://www.emix8.org/forum/viewtopic.php?p=5446

*/

// Constants

const int SV_NOTECMD_NOTE_OFF = 128;
const int SV_NOTECMD_ALL_NOTES_OFF  = 129; // notes of all synths off
const int SV_NOTECMD_CLEAN_SYNTHS = 130; // stop and clean all synths
const int SV_NOTECMD_STOP = 131;
const int SV_NOTECMD_PLAY = 132;

const int SV_INIT_FLAG_NO_DEBUG_OUTPUT = 1 << 0;
const int SV_INIT_FLAG_USER_AUDIO_CALLBACK = 1 << 1;
const int SV_INIT_FLAG_AUDIO_INT16 = 1 << 2;
const int SV_INIT_FLAG_AUDIO_FLOAT32 = 1 << 3;
const int SV_INIT_FLAG_ONE_THREAD =  1 << 4;

const int SV_MODULE_FLAG_EXISTS = 1;
const int SV_MODULE_FLAG_EFFECT = 2;
const int SV_MODULE_INPUTS_OFF = 16;
const int SV_MODULE_INPUTS_MASK = ( 255 << SV_MODULE_INPUTS_OFF );
const int SV_MODULE_OUTPUTS_OFF = ( 16 + 8 );
const int SV_MODULE_OUTPUTS_MASK = ( 255 << SV_MODULE_OUTPUTS_OFF );

const int SV_STYPE_INT16 = 0;
const int SV_STYPE_INT32 = 1;
const int SV_STYPE_FLOAT32 = 2;
const int SV_STYPE_FLOAT64 = 3;

// Initialization functions

int sv_init(string dev, int freq, int channels, int flags) {}
int sv_deinit() {}
int sv_open_slot(int slot) {}
int sv_close_slot(int slot) {}
//int sv_lock_slot(int slot ) {}
//int sv_unlock_slot(int slot) {}
int sv_load(int slot, string name) {}
int sv_load_from_memory(int slot, xptr data, int data_size) {}

// Functions to control song playing

int sv_play(int slot) {}
int sv_play_from_beginning(int slot) {}
int sv_stop(int slot) {}
int sv_set_autostop(int slot, int autostop) {}
  // autostop values: 0 - disable autostop; 1 - enable autostop.
  // When disabled, song is playing infinitely in the loop.
//int sv_rewind(int slot, int t) {}
int sv_volume(int slot, int vol) {}
int sv_send_event(int slot, int channel_num, int note, int vel, int module, int ctl, int ctl_val) {}

// Functions to get info about the engine, song and its playing

int sv_audio_callback(xptr buf, int frames, int latency, int out_time) {}
  // Get the next piece of SunVox audio.
  // buf - destination buffer of type signed short (if SV_INIT_FLAG_AUDIO_INT16 used in sv_init())
  //       or float (if SV_INIT_FLAG_AUDIO_FLOAT32 used in sv_init());
  //       stereo data will be interleaved in this buffer: LRLR... ; where the LR is the one frame;
  // frames - number of frames in destination buffer;
  // latency - audio latency (in frames);
  // out_time - output time (in ticks).
int sv_get_sample_type() {}
  // Get internal sample type of the SunVox engine.
  // Return value: one of the SV_STYPE_xxx defines.
  // Use it to get the scope buffer type from get_module_scope() function.
int sv_end_of_song(int slot) {}
  // Return values: 0 - song is playing now; 1 - stopped.
int sv_get_current_line(int slot) {}
int sv_get_current_signal_level(int slot, int channel) {}

string sv_get_song_name(int slot) {}

int sv_get_song_bpm(int slot) {}
int sv_get_song_tpl(int slot) {}
int sv_get_song_length_lines(int slot) {}
int sv_get_song_length_frames(int slot) {}
  // Frame is one discrete of the sound. Sampling frequency 44100 Hz
  // means, that you hear 44100 frames per second.
int sv_get_ticks() {}
  // Returns the current tick counter (from 0 to 0xFFFFFFFF).
  // SunVox engine uses its own time space, measured in ticks.
int sv_get_ticks_per_second() {}
  // Returns the number of SunVox ticks per second.
int sv_get_number_of_modules(int slot) {}
int sv_get_module_flags(int slot, int mod_num) {}
string sv_get_module_name(int slot, int mod_num) {}
int[] sv_get_module_inputs(int slot, int mod_num) {}
int[] sv_get_module_outputs(int slot, int mod_num) {}
int sv_get_module_xy(int slot, int mod_num) {}
int sv_get_module_color(int slot, int mod_num) {}
byte[] sv_get_module_scope(int slot, int mod_num, int channel, int[] offset, int[] buffer_size) {}
int sv_get_number_of_patterns(int slot) {}
int sv_get_pattern_x(int slot, int pat_num) {}
int sv_get_pattern_y(int slot, int pat_num) {}
int sv_get_pattern_tracks(int slot, int pat_num) {}
int sv_get_pattern_lines(int slot, int pat_num) {}
byte[] sv_get_pattern_data(int slot, int pat_num) {}
  // Returns array of structures:
  // typedef struct {
  //   unsigned char  note;    // 0 - nothing; 1..127 - note num; 128 - note off; 129, 130... - see NOTECMD_xxx
  //   unsigned char  vel;     // Velocity 1..129; 0 - default
  //   unsigned char  module;  // 0 - nothing; 1..255 - module number
  //   unsigned char  nothing;
  //   unsigned short ctl;     // CCXX. CC - number of controller. XX - std effect
  //   unsigned short ctl_val; // Value of controller
  // } sunvox_note;
int sv_pattern_mute(int slot, int pat_num, int mute) {}
  // Use it with sv_lock_slot() and sv_unlock_slot()
Can I simply add sv_get_module_ctl_value to that list?
User avatar
Kjell
Posts: 1945
Joined: Sat Feb 23, 2008 11:15 pm

Re: Help with Sunvox volume and json

Post by Kjell »

Hi Ats,

The ZExternalLibrary that Rado1 made for SunVox is simply a direct "interface" to the SunVox DLL ( similar to the OpenGL ZExternalLibrary ), there's no wrapper involved. So yes, you can simply add any missing API function.

Code: Select all

int sv_get_module_ctl_value(int slot, int mod_num, int ctl_num, int scaled){}
K
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Help with Sunvox volume and json

Post by Ats »

Oh wow. It worked perfectly:

Code: Select all

void ListMusicModules()
{
  // Get the total number of modules
  int num_modules = sv_get_number_of_modules(0);

  // Loop through each module and print its name and volume
  for (int i = 0; i < num_modules; i++) {
      string module_name = sv_get_module_name(0, i);
      int volume = sv_get_module_ctl_value(0, i, 0, 0);
      trace("Module " + intToStr(i) + ": " + module_name + "  vol: " + intToStr(volume));
  }
}
Thanks :D
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Ats »

After some reflection, I realized I’m going to need to read an external file to make tweaks on the modules without having to compile an EXE. It’s for the musician :)

Right now, I’m saving the modules’ volumes in an array when I first scan the SunVox files:

Code: Select all

void ListMusicModules() {
  // Get the total number of modules
  int num_modules = sv_get_number_of_modules(0);
  MusicModules_Retaliation.SizeDim1 = num_modules;

  // Loop through each module and print its name
  for (int i = 0; i < num_modules; i++) {
      string module_name = sv_get_module_name(0, i);
      int volume = sv_get_module_ctl_value(0, i, 0, 1);
      trace("Module " + intToStr(i) + ": " + module_name + "  " + intToStr(volume));
      MusicModules_Retaliation[i] = volume;
  }
}
Then I made a simple test to see how the music status works:

Code: Select all

void SetMusicStatus(string action) {
    trace("Set music status to " + action);

    switch(action)
    {
      case "normal":
      // Set the module volumes to their original state
      for(int i = 0; i < MusicModules_Retaliation.SizeDim1; i++) {
          sv_send_event(0, 1, 0, 0, i + 1, 0x0100, MusicModules_Retaliation[i]);
      }
      break;

      case "pause":
      // sv_send_event(0, 1, 0, 0, 0+1, 0x0100, 0);  // output
      sv_send_event(0, 1, 0, 0, 1+1, 0x0100, 10000);  // syn2
      // sv_send_event(0, 1, 0, 0, 2+1, 0x0100, 8192);  // Amplifier
      sv_send_event(0, 1, 0, 0, 3+1, 0x0100, 0);  // fx2 noise
      sv_send_event(0, 1, 0, 0, 4+1, 0x0100, 0);  // cr
      sv_send_event(0, 1, 0, 0, 5+1, 0x0100, 0);  // cc2
      sv_send_event(0, 1, 0, 0, 6+1, 0x0100, 0);  // syn2
      sv_send_event(0, 1, 0, 0, 7+1, 0x0100, 10000);  // bass2
      sv_send_event(0, 1, 0, 0, 8+1, 0x0100, 0);  // gt2
      sv_send_event(0, 1, 0, 0, 9+1, 0x0100, 0);  // fx1 vib
      sv_send_event(0, 1, 0, 0, 10+1, 0x0100, 0);  // guit1
      sv_send_event(0, 1, 0, 0, 11+1, 0x0100, 6800);  // pad
      // sv_send_event(0, 1, 0, 0, 12+1, 0x0100, 32768);  // Echo
      sv_send_event(0, 1, 0, 0, 13+1, 0x0100, 0);  // gc2
      // sv_send_event(0, 1, 0, 0, 14+1, 0x0100, 0);  // ???
      sv_send_event(0, 1, 0, 0, 15+1, 0x0100, 0);  // hh2
      sv_send_event(0, 1, 0, 0, 16+1, 0x0100, 0);  // syn1
      // sv_send_event(0, 1, 0, 0, 17+1, 0x0100, 0);  // ???
      // sv_send_event(0, 1, 0, 0, 18+1, 0x0100, 0);  // ???
      // sv_send_event(0, 1, 0, 0, 19+1, 0x0100, 0);  // ???
      break;
    }
}
I believe ZGE can read txt files. Maybe it could open music_pause.txt and read something like:
0,10000,8192,0,0,0,0,10000,0,0,0,6800,32768,0,0,0,0,0,0,0
to set the volumes on the modules?
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Ats »

I managed to read my list of numbers from the txt file, but that seems overly complicated. Am I doing it right?

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
  <OnLoaded>
    <FileAction Comment="Read number.txt" File="NumberFile"/>
    <ZExpression>
      <Expression>
<![CDATA[//int Numbers[] = {};
Numbers.SizeDim1 = 0;

// Assume NumberBuffer has the file contents
if (NumberFile.Size)
{
  string line = "";

  for (int i=0; i<NumberBuffer.SizeDim1; i++)
  {
    string c = chr(NumberBuffer[i]);

    if (c == ",")
    {
      if (length(line) > 0)
      {
        Numbers.SizeDim1++;
        Numbers[Numbers.SizeDim1-1] = strToInt(line);
        line = "";
      }
    }
    else
    {
      line += c;
    }
  }

  // Handle last number if file doesn’t end with comma
  if (length(line) > 0)
  {
    Numbers.SizeDim1++;
    Numbers[Numbers.SizeDim1-1] = strToInt(line);
  }

  // Show all numbers for testing
  NumberText.text = "";
  for (int j=0; j<Numbers.SizeDim1; j++)
  {
    NumberText.Text += intToStr(Numbers[j]) + "\n";
  }
}
else
{
  NumberText.Text = "ERROR?";
}]]>
      </Expression>
    </ZExpression>
  </OnLoaded>
  <OnRender>
    <RenderText Name="NumberText" X="-0.5" Y="0.8" Scale="0.5"/>
  </OnRender>
  <Content>
    <Array Name="NumberBuffer" Type="4" SizeDim1="58"/>
    <File Name="NumberFile" FileName="music.txt" TargetArray="NumberBuffer"/>
    <Array Name="Numbers" Type="1" SizeDim1="58"/>
  </Content>
</ZApplication>
User avatar
Kjell
Posts: 1945
Joined: Sat Feb 23, 2008 11:15 pm

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Kjell »

Hi Ats,
Ats wrote: Mon Aug 18, 2025 11:17 pmAm I doing it right?
It's easier when using a line per value instead of separating by comma. For example:

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
  <OnLoaded>
    <ZExpression>
      <Expression>
<![CDATA[// Read from file & convert

@FileAction(File: DataFile);
Data.SizeDim1 = DataLines.SizeDim1;
DataText.Text = "";

for(int i=0; i<DataLines.SizeDim1; i++)
{
  Data[i] = strToInt(DataLines[i]);
  DataText.Text += DataLines[i] + "\n";
}]]>
      </Expression>
    </ZExpression>
  </OnLoaded>
  <OnRender>
    <RenderText Name="DataText" X="-0.5" Y="0.5" Scale="0.25" Align="1"/>
  </OnRender>
  <Content>
    <Array Name="Data" Type="1" Persistent="255"/>
    <File Name="DataFile" FileName="data.txt" TargetArray="DataLines"/>
    <Array Name="DataLines" Type="2"/>
  </Content>
</ZApplication>
In combination with the following "data.txt":

Code: Select all

0
10000
8192
0
0
0
0
10000
0
0
0
6800
32768
0
0
0
0
0
0
0
K
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Ats »

Oh yeah, I overdid it :lol:
Thanks a lot!
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Ats »

Hahaha I have one last problem regarding the same number storage within the game :lol:
When my game isn’t in DEBUG_MUSIC mode, I would like to embed the volumes of the music instruments directly in the game, instead of relying on external text files.

Typically, in other languages, I would store my arrays somewhere in plain text (easy to copy/paste if I need to tweak them later):

Code: Select all

Music1_Action = [10, 300, 80]; // For the exemple, I don't list all the volumes
Music1_Pause = [0, 20, 20];
Music2_Action = [256, 100, 0, 180, 50]; // there are more modules in music 2
Music2_Pause = [300, 10, 60, 60, 100];
Then, depending on the current music and status, I would assign the target volumes array like this:

Code: Select all

MusicTargetVolumes = Music1_Action;
But in ZGE, storing arrays in a zlibrary isn’t as neat:

Code: Select all

{
 Music1_Action.SizeDim1 = 3;
 Music1_Action[0] = 10;
 Music1_Action[1] = 300;
 Music1_Action[2] = 80;
}
With Music1_Action declared somewhere else:

Code: Select all

<Array Name="Music1_Action" />
And so on…

And then, I would have to do something like this:

Code: Select all

MusicTargetVolumes.SizeDim1 = Music1_Action.SizeDim1;  
for (int i = 0; i < MusicTargetVolumes.SizeDim1; i++) {  
    MusicTargetVolumes[i] = Music1_Action[i];  
}
And that’s just for the first status of the first music… because I don’t think functions in ZGE can pass arrays.

So I was wondering if there’s a better way to store those numbers and use them. Maybe I could store them as a string instead? Something like:

Code: Select all

string RetrieveMusicData(string music, string status) {  
    string name = music + "_" + status;  
    switch (name) {  
        case "Music1_Action": return "10,300,80"; break;  
        ...  
    }  
}
And later, I could split the retrieved string into numbers and copy them into the MusicTargetVolumes array. I don’t know…
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Ats »

Maybe this is the simplest way to achieve this:

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
  <OnLoaded>
    <ZLibrary Comment="Music Volumes" HasInitializer="1">
      <Source>
<![CDATA[{Music1_Action.SizeDim1=3;Music1_Action[0]=10;Music1_Action[1]=300;Music1_Action[2]=80;}
{Music1_Pause.SizeDim1=3;Music1_Pause[0]=0;Music1_Pause[1]=20;Music1_Pause[2]=20;}
{Music2_Action.SizeDim1=5;Music2_Action[0]=256;Music2_Action[1]=100;Music2_Action[2]=0;Music2_Action[3]=180;Music2_Action[4]=50;}
{Music2_Pause.SizeDim1=5;Music2_Pause[0]=300;Music2_Pause[1]=10;Music2_Pause[2]=60;Music2_Pause[3]=60;Music2_Pause[4]=100;}]]>
      </Source>
    </ZLibrary>
    <ZLibrary>
      <Source>
<![CDATA[void RetrieveMusicData(string music, string status) {
    string name = music + "_" + status;
    switch (name) {
      case "Music1_Action":
      MusicTargetVolumes.SizeDim1 = Music1_Action.SizeDim1;
      for (int i = 0; i < MusicTargetVolumes.SizeDim1; i++) MusicTargetVolumes[i] = Music1_Action[i];
      break;
      case "Music1_Pause":
      MusicTargetVolumes.SizeDim1 = Music1_Pause.SizeDim1;
      for (int i = 0; i < MusicTargetVolumes.SizeDim1; i++) MusicTargetVolumes[i] = Music1_Pause[i];
      break;
      case "Music2_Action":
      MusicTargetVolumes.SizeDim1 = Music2_Action.SizeDim1;
      for (int i = 0; i < MusicTargetVolumes.SizeDim1; i++) MusicTargetVolumes[i] = Music2_Action[i];
      break;
      case "Music2_Pause":
      MusicTargetVolumes.SizeDim1 = Music2_Pause.SizeDim1;
      for (int i = 0; i < MusicTargetVolumes.SizeDim1; i++) MusicTargetVolumes[i] = Music2_Pause[i];
      break;
    }
}]]>
      </Source>
    </ZLibrary>
    <ZExpression>
      <Expression>
<![CDATA[RetrieveMusicData("Music2", "Pause");
for (int i=0; i<MusicTargetVolumes.SizeDim1; i++) trace(intToStr(MusicTargetVolumes[i]));]]>
      </Expression>
    </ZExpression>
  </OnLoaded>
  <Content>
    <Array Name="MusicTargetVolumes" Type="1" SizeDim1="5"/>
    <Array Name="Music1_Action" Type="1" SizeDim1="3"/>
    <Array Name="Music1_Pause" Type="1" SizeDim1="3"/>
    <Array Name="Music2_Action" Type="1" SizeDim1="5"/>
    <Array Name="Music2_Pause" Type="1" SizeDim1="5"/>
  </Content>
</ZApplication>
I need to focus hard when writing it the first time to avoid errors, but then I can write a little script that will transform the numbers from a sheet into this:

Code: Select all

{Music1_Action.SizeDim1=3;Music1_Action[0]=10;Music1_Action[1]=300;Music1_Action[2]=80;}
{Music1_Pause.SizeDim1=3;Music1_Pause[0]=0;Music1_Pause[1]=20;Music1_Pause[2]=20;}
{Music2_Action.SizeDim1=5;Music2_Action[0]=256;Music2_Action[1]=100;Music2_Action[2]=0;Music2_Action[3]=180;Music2_Action[4]=50;}
{Music2_Pause.SizeDim1=5;Music2_Pause[0]=300;Music2_Pause[1]=10;Music2_Pause[2]=60;Music2_Pause[3]=60;Music2_Pause[4]=100;}
Just as I did will all the other external data in my game :wink:
User avatar
Kjell
Posts: 1945
Joined: Sat Feb 23, 2008 11:15 pm

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Kjell »

Hi Ats,
Ats wrote: Thu Aug 21, 2025 7:09 amI would like to embed the volumes of the music instruments directly in the game, instead of relying on external text files.
I guess that's why the File component has the FileEmbedded property :wink:

Image
Ats wrote: Thu Aug 21, 2025 7:09 amI don’t think functions in ZGE can pass arrays.
You can, you could for example do something like this ( press 1,2,3,4 on keyboard ):

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
  <OnLoaded>
    <ZLibrary>
      <Source>
<![CDATA[//

void setVolumes(int[] data)
{
  Demo.Text = "";

  for(int i=0; i<data.SizeDim1; i++)
  {
    if(i)Demo.Text += ",";
    Demo.Text += intToStr(data[i]);
  }
}]]>
      </Source>
    </ZLibrary>
  </OnLoaded>
  <OnUpdate>
    <KeyPress Name="Key" Keys="1234">
      <OnKeyDown>
        <ZExpression>
          <Expression>
<![CDATA[//

int[] music1_action = {8,7,9};
int[] music1_paused = {3,2,4};

int[] music2_action = {8,9,7,8};
int[] music2_paused = {2,3,1,2};

//

switch(Key.KeyIndex)
{
  case 0: setVolumes(music1_action); break;
  case 1: setVolumes(music1_paused); break;
  case 2: setVolumes(music2_action); break;
  case 3: setVolumes(music2_paused); break;
}]]>
          </Expression>
        </ZExpression>
      </OnKeyDown>
    </KeyPress>
  </OnUpdate>
  <OnRender>
    <RenderText Name="Demo"/>
  </OnRender>
</ZApplication>
Ats wrote: Thu Aug 21, 2025 7:09 amSo I was wondering if there’s a better way to store those numbers and use them.
I'd probably use persistent arrays myself.

K
User avatar
Ats
Posts: 853
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: [Solved] Help to get Sunvox module volume (maybe using json?)

Post by Ats »

Kjell wrote:I guess that's why the File component has the FileEmbedded property :wink:
I guess you are right. My method make sense for all the spaceship datas that are stored, modified and generated from the sheet, but for the music volumes, since the txt files already exist, that makes total sense.
Kjell wrote:You can, you could for example do something like this ( press 1,2,3,4 on keyboard )
WHAT!? And it works both ways. I have no idea what I did wrong this morning while testing arrays in functions.

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
  <OnLoaded>
    <ZLibrary>
      <Source>
<![CDATA[//

int[] testArray()
{
   return MusicTargetVolumes;
}

void setVolumes(int[] data)
{
  MusicTargetVolumes.SizeDim1 = data.SizeDim1;

  for(int i=0; i<MusicTargetVolumes.SizeDim1; i++)
  {
    MusicTargetVolumes[i] = data[i];
  }

  int[] a = testArray();
  for(int j=0; j<a.SizeDim1; j++) trace(intToStr(a[j]));
}]]>
      </Source>
    </ZLibrary>
  </OnLoaded>
  <OnUpdate>
    <KeyPress Name="Key" Keys="1234">
      <OnKeyDown>
        <ZExpression>
          <Expression>
<![CDATA[//

int[] music1_action = {8,7,9};
int[] music1_paused = {3,2,4};

int[] music2_action = {8,9,7,8};
int[] music2_paused = {2,3,1,2};

//

switch(Key.KeyIndex)
{
  case 0: setVolumes(music1_action); break;
  case 1: setVolumes(music1_paused); break;
  case 2: setVolumes(music2_action); break;
  case 3: setVolumes(music2_paused); break;
}]]>
          </Expression>
        </ZExpression>
      </OnKeyDown>
    </KeyPress>
  </OnUpdate>
  <Content>
    <Array Name="MusicTargetVolumes" Type="1" SizeDim1="4"/>
  </Content>
</ZApplication>
All right. Both methods work for me. I need to think about how I’ll use those numbers in the future. Thanks again!
Post Reply