SFXR

Post screenshots, binaries and projectfiles of the projects you have made with ZGE that you want to share!

Moderator: Moderators

User avatar
VilleK
Site Admin
Posts: 2324
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: SFXR

Post by VilleK »

Kjell sent me an example that pinpointed the problem. Please update ZGE, it works here now.
User avatar
Ats
Posts: 716
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: SFXR

Post by Ats »

Thanks, both of you.
So here's my last zsfxr test, which preloads 100 sounds (10 sounds per type, but tone isn't the most interesting).
I deactivated the Random sounds and the Right click mutation.
During the initialization of the sound, as suggested by Kjell, I'm playing them once, all while checking if the Sample index has reached the desired Sample length before moving on to the next sound init. But since I'm not sure what exactly was repaired in the last release of ZGE, I don't know if I still have to do that.
The result is that it takes rather long to initialize 100 sounds. But at least, it is working :wink:

Edit:
And here's the APK. It isn't crashing anymore on Android, which is very cool. And if I generate only lasers and explosions, it should be good to go for Omeganaut.
Attachments
ZSFXR.0.1.1.apk
(245.76 KiB) Downloaded 125 times
ZSFXR_preload_samples.zgeproj
(101.13 KiB) Downloaded 141 times
User avatar
Ats
Posts: 716
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: SFXR

Post by Ats »

I've started writing a moulinette (= conversion tool, in french) to convert jsfxr sound serialization from :

Code: Select all

{
  "oldParams": true,
  "wave_type": 3,
  "p_env_attack": 0,
  "p_env_sustain": 1,
  "p_env_punch": 0.35304476503997884,
  "p_env_decay": 1,
  "p_base_freq": 0.7287884051487694,
  "p_freq_limit": 0,
  "p_freq_ramp": 0.003089916083175466,
  "p_freq_dramp": 0.5464092134956474,
  "p_vib_strength": 0.0006601438087948627,
  "p_vib_speed": -0.47612845336164744,
  "p_arp_mod": -0.18785615002377387,
  "p_arp_speed": 0.7628857641806879,
  "p_duty": 0.031237783903733884,
  "p_duty_ramp": -0.05899195813974674,
  "p_repeat_speed": 0.41017668270216534,
  "p_pha_offset": 0.011909400002449685,
  "p_pha_ramp": 0.009166784366338953,
  "p_lpf_freq": 0.12745521184461372,
  "p_lpf_ramp": -0.02388602723340759,
  "p_lpf_resonance": -0.7126283887429805,
  "p_hpf_freq": 2.128612277679578e-12,
  "p_hpf_ramp": 0.021328559525873432,
  "sound_vol": 0.25,
  "sample_rate": 44100,
  "sample_size": 8
}
into something usable for ZGE. Maybe something like:

Code: Select all

{SoundData.SizeDim1=22;SoundData[0]=3;SoundData[1]=0;SoundData[2]=1;SoundData[3]=0.35304476;SoundData[4]=1;SoundData[5]=0.72878840;SoundData[6]=0;SoundData[7]=0.00308991;SoundData[8]=0.54640921;SoundData[9]=0.00066014;SoundData[10]=-0.47612845;SoundData[11]=-0.18785615;SoundData[12]=0.76288576;SoundData[13]=0.03123778;SoundData[14]=-0.05899195;SoundData[15]=0.41017668;SoundData[16]=0.01190940;SoundData[17]=0.00916678;SoundData[18]=0.12745521;SoundData[19]=-0.02388602;SoundData[20]=-0.71262838;SoundData[21]=2.12861227;SoundData[22]=0.02132855;}
Here, SoundData is an array that contains the description of one sound.
549 characters + one array size 22 per sound.

I know that declaring arrays like that isn't sexy, but at least I can simply copy/paste the line from my spreadsheet that contains the data and generates this line of code. Or since it's only needed once during the initialization, skip the array and directly convert the serialization to:

Code: Select all

case SoundData:p_env_attack=0;p_env_sustain=1;p_env_punch=0.35304476;p_env_decay=1;p_base_freq=0.72878840;p_freq_limit=0;p_freq_ramp=0.00308991;p_freq_dramp=0.54640921;p_vib_strength=0.00066014;p_vib_speed=-0.47612845;p_arp_mod=-0.18785615;p_arp_speed=0.76288576;p_duty=0.03123778;p_duty_ramp=-0.05899195;p_repeat_speed=0.41017668;p_pha_offset=0.01190940;p_pha_ramp=0.00916678;p_lpf_freq=0.12745521;p_lpf_ramp=-0.02388602;p_lpf_resonance=-0.71262838;p_hpf_freq=2.12861227;p_hpf_ramp=0.02132855;break;
Here, SoundData is an int to get the description of the corresponding sound number inside a switch.
500 characters + one int per sound. This should be better.

Apart FilterCutoff and FilterQ, are there other ZGE filters that can be applied in real time to those generated sounds? Like BaseNoteNr or Osc1Waveform? Are those filters instantaneous when playing the sound? I'm a noob when it comes to synth :lol:
User avatar
Kjell
Posts: 1911
Joined: Sat Feb 23, 2008 11:15 pm

Re: SFXR

Post by Kjell »

Hi Ats,
Ats wrote: Fri May 03, 2024 6:55 pmApart FilterCutoff and FilterQ, are there other ZGE filters that can be applied in real time to those generated sounds? Like BaseNoteNr or Osc1Waveform? Are those filters instantaneous when playing the sound? I'm a noob when it comes to synth :lol:
If your Sound component uses a Sample it overrides "Oscillator 1", but aside from that you can still use all other features including Modulators, LFOs and Envelopes. Do keep in mind that most of these features are updated per-frame ( not sub-frame / per-sample ), so any significant changes from frame-to-frame will result in crackling audio artifacts.

And just to illustrate what that entails .. below are two sine waveforms ( one high frequency & one super-high frequency ) sampled per-frame ( at 100fps ), sampled per-frame using linear interpolation, and sampled per-sample:

Image

Image

Image

A sine-wave at 2750Hz ( which is already pretty high frequency ): linear interpolation is pretty close to per-sample, so in this region i'd say lerp is the best balance between accuracy and performance.

Image

Image

Image

A sine-wave at 11kHz ( which is higher frequency than you'd realistically ever use ): both per-frame and linear interpolation have a significantly different signature from per-sample .. but at least lerp doesn't have the jumps ( causing pops & cracks ) of per-frame.

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

Re: SFXR

Post by Ats »

Thanks for the explanations :)

Here's a simplified version of ZSFXR that initialize sounds from preset function that is generated by my Google Sheet. By the way, two decimals is enough to define the sound parameters. It works really well! (mouse click the app)

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZSFXR" ScreenMode="1" MouseVisible="255" FileVersion="2">
  <OnLoaded>
    <ZLibrary Comment="GENERATED FUNCTION - SOUNDS" HasInitializer="1">
      <Source>
<![CDATA[void initSoundParam(int s){
  switch(s){
    case 0:
    wave_type=3;p_env_attack=0;p_env_sustain=0.2;p_env_punch=0.75;p_env_decay=0.51;p_base_freq=0.14;p_freq_limit=0;p_freq_ramp=-0.13;p_freq_dramp=0;p_vib_strength=0;p_vib_speed=0;p_arp_mod=0.51;p_arp_speed=0.77;p_duty=0;p_duty_ramp=0;p_repeat_speed=0;p_pha_offset=0;p_pha_ramp=0;p_lpf_freq=1;p_lpf_ramp=0;p_lpf_resonance=0;p_hpf_freq=0;p_hpf_ramp=0;
    break;
    case 1:
    wave_type=1;p_env_attack=0;p_env_sustain=0.37;p_env_punch=0;p_env_decay=0.37;p_base_freq=0.54;p_freq_limit=0;p_freq_ramp=0.3;p_freq_dramp=0;p_vib_strength=0;p_vib_speed=0;p_arp_mod=0;p_arp_speed=0;p_duty=1;p_duty_ramp=0;p_repeat_speed=0.47;p_pha_offset=0;p_pha_ramp=0;p_lpf_freq=1;p_lpf_ramp=0;p_lpf_resonance=0;p_hpf_freq=0;p_hpf_ramp=0;
    break;
    case 2:
    wave_type=2;p_env_attack=0;p_env_sustain=0.28;p_env_punch=0.14;p_env_decay=0.38;p_base_freq=0.58;p_freq_limit=0.2;p_freq_ramp=-0.22;p_freq_dramp=0;p_vib_strength=0;p_vib_speed=0;p_arp_mod=0;p_arp_speed=0;p_duty=0.83;p_duty_ramp=-0.55;p_repeat_speed=0;p_pha_offset=0;p_pha_ramp=0;p_lpf_freq=1;p_lpf_ramp=0;p_lpf_resonance=0;p_hpf_freq=0.19;p_hpf_ramp=0;
    break;
  }
}

Sample getSampleName(int s){
  switch(s){
    case 0:return Sample_Explosion;
    case 1:return Sample_PowerUp;
    case 2:return Sample_Laser;
  }
}

byte MAXSAMPLES=3;]]>
      </Source>
    </ZLibrary>
    <ZLibrary Comment="SFXR">
      <Source>
<![CDATA[//

float SampleLength()
{
  return (p_env_attack*p_env_attack+
          p_env_sustain*p_env_sustain+
          p_env_decay*p_env_decay)*100000;
}

//

void ResetSample(int restart)
{
  // Base

  if(!restart)phase = 0;

  period = 100/(p_base_freq*p_base_freq+0.001);
  fperiod = period;
  fmaxperiod = 100/(p_freq_limit*p_freq_limit+0.001);

  fslide = 1-pow(p_freq_ramp,3)*0.01;
  fdslide = pow(p_freq_dramp,3)*-0.000001;

  // Square

  square_duty = 0.5-p_duty*0.5;
  square_slide = p_duty_ramp*-0.00005;

  // Arpeggio

  arp_time = 0;
  arp_limit = p_arp_speed != 1 ? pow(1-p_arp_speed,2)*20000+32 : 0;
  arp_mod = p_arp_mod >= 0 ? 1-pow(p_arp_mod,2)*0.9 : 1+pow(p_arp_mod,2)*10;

  if(!restart)
  {
    sampling = 1;

    // Filter

    fltp = 0;
    fltdp = 0;
    fltw = pow(p_lpf_freq,3)*0.1;
    fltw_d = 1+p_lpf_ramp*0.0001;

    fltdmp = 5/(1+pow(p_lpf_resonance,2)*20)*(0.01+fltw);
    if(fltdmp > 0.8)fltdmp = 0.8;

    fltphp = 0;
    flthp = pow(p_hpf_freq,2)*0.1;
    flthp_d = 1+p_hpf_ramp*0.0003;

    // Vibrato

    vib_phase = 0;
    vib_speed = pow(p_vib_speed,2)*0.01;
    vib_amp = p_vib_strength*0.5;

    // Envelope

    env_stage = 0;
    env_time = 0;

    env_length[0] = p_env_attack*p_env_attack*100000;
    env_length[1] = p_env_sustain*p_env_sustain*100000;
    env_length[2] = p_env_decay*p_env_decay*100000;

    // Phaser

    fphase = pow(p_pha_offset,2)*1020;
    if(p_pha_offset < 0)fphase *= -1;

    fdphase = pow(p_pha_ramp,2);
    if(p_pha_ramp < 0)fdphase *= -1;

    iphase = fphase;
    ipp = 0;

    // Noise

    fnoise = rnd()*2-1;
    ppnoise = 0;

    // Repeat

    rep_time = 0;
    rep_limit = p_repeat_speed ? pow(1-p_repeat_speed,2)*20000+32 : 0;
  }
}

//

void SynthSample(int start, int end, int quality)
{
  // Repeat

  float l_rep_time = rep_time;
  float l_rep_limit = rep_limit;

  // Arpeggio

  float l_arp_time = arp_time;
  float l_arp_mod = arp_mod;
  float l_arp_limit = arp_limit;

  // Base

  int l_wave_type = wave_type;

  float l_phase = phase;
  float l_period = period;
  float l_fperiod = fperiod;
  float l_fmaxperiod = fmaxperiod;
  float l_fslide = fslide;
  float l_fdslide = fdslide;

  // Square

  float l_square_duty = square_duty;
  float l_square_slide = square_slide;

  // Vibrato

  float l_vib_phase = vib_phase;
  float l_vib_speed = vib_speed;
  float l_vib_amp = vib_amp;

  // Envelope

  float l_env_vol;
  float l_env_length;

  float l_env_stage = env_stage;
  float l_env_time = env_time;

  float l_env_punch = p_env_punch;

  float l_env_length_0 = env_length[0];
  float l_env_length_1 = env_length[1];
  float l_env_length_2 = env_length[2];

  // Noise

  float l_fnoise = fnoise;
  int l_ppnoise = ppnoise;

  // Phaser

  float l_fphase = fphase;
  float l_fdphase = fdphase;

  int l_iphase = iphase;
  int l_ipp = ipp;

  // Filter

  float l_lpf_freq = p_lpf_freq;

  float l_fltp = fltp;
  float l_fltdp = fltdp;
  float l_fltdmp = fltdmp;

  float l_flthp = flthp;
  float l_flthp_d = flthp_d;

  float l_fltw = fltw;
  float l_fltw_d = fltw_d;

  float l_fltphp = fltphp;

  // Supersampler

  float sp = pow(2,quality);
  float ss = 8/sp;

  // Synth

  int l_sampling = sampling;

  for(int i=start; i<end; i++)
  {
    if(!l_sampling)
    {
      buffer[i] = 0;
      continue;
    }

    // Repeat

    if(l_rep_limit)
    {
      l_rep_time++;

      if(l_rep_time >= l_rep_limit)
      {
        l_rep_time = 0;
        ResetSample(1);

        // Local

        l_period = period;
        l_fperiod = fperiod;
        l_fslide = fslide;

        l_square_duty = square_duty;

        l_arp_time = arp_time;
        l_arp_limit = arp_limit;
      }
    }

    // Arpeggio

    l_arp_time++;

    if(l_arp_limit != 0 && l_arp_time >= l_arp_limit)
    {
      l_arp_limit = 0;
      l_fperiod *= l_arp_mod;
    }

    // Base

    l_fslide += l_fdslide;
    l_fperiod *= l_fslide;

    if(l_fperiod > l_fmaxperiod)
    {
      l_fperiod = l_fmaxperiod;
      l_sampling = 0;
    }

    // Square

    if(l_wave_type == 0)
    {
      l_square_duty += l_square_slide;
      if(l_square_duty < 0)l_square_duty = 0;
      if(l_square_duty > 0.5)l_square_duty = 0.5;
    }

    // Vibrato

    float rfperiod = l_fperiod;

    if(l_vib_amp > 0)
    {
      l_vib_phase += l_vib_speed;
      rfperiod = l_fperiod*(1+sin(l_vib_phase)*l_vib_amp);
    }

    l_period = rfperiod;
    if(l_period < 8)l_period = 8;

    // Envelope

    l_env_time++;

    switch(l_env_stage)
    {
      case 0: l_env_length = l_env_length_0; break;
      case 1: l_env_length = l_env_length_1; break;
      case 2: l_env_length = l_env_length_2; break;
    }

    if(l_env_time > l_env_length)
    {
      l_env_time = 0;
      l_env_stage++;
    }

    float tl = l_env_time ? l_env_time/l_env_length : 0;

    switch(l_env_stage)
    {
      case 0: l_env_vol = tl; break;
      case 1: l_env_vol = 1+(1-tl)*2*l_env_punch; break;
      case 2: l_env_vol = 1-tl; break;
    }

    // Phaser

    if(l_fphase || l_fdphase)
    {
      l_fphase += l_fdphase;
      l_iphase = abs(l_fphase);
      if(l_iphase > 1023)l_iphase = 1023;
    }

    // Filter

    if(l_flthp_d != 0)
    {
      l_flthp *= l_flthp_d;
      if(l_flthp < 0.00001)l_flthp = 0.00001;
      if(l_flthp > 0.1)l_flthp = 0.1;
    }

    // Supersampler

    float ssample = 0;

    for(int si=0; si<sp; si++)
    {
      float sample = 0;

      l_phase += ss;

      if(l_phase >= l_period)l_phase = l_phase-floor(l_phase/l_period)*l_period;

      float fp = l_phase/l_period;


      switch(l_wave_type)
      {
        case 0: sample = fp < l_square_duty ? -0.5 : 0.5; break;
        case 1: sample = 1-fp*2; break;
        case 2: sample = sin(fp*PI*2); break;
        case 3: int pnoise = fp*32;
                if(pnoise != l_ppnoise){l_fnoise = rnd()*2-1; l_ppnoise = pnoise;}
                sample = l_fnoise; break;
      }

      // Filter

      float pp = l_fltp;
      l_fltw *= l_fltw_d;

      if(l_fltw < 0)l_fltw = 0;
      if(l_fltw > 0.1)l_fltw = 0.1;

      if(l_lpf_freq != 1)
      {
        l_fltdp += (sample-l_fltp)*l_fltw;
        l_fltdp -= l_fltdp*l_fltdmp;
      }
      else
      {
        l_fltp = sample;
        l_fltdp = 0;
      }

      l_fltp += l_fltdp;

      l_fltphp += l_fltp-pp;
      l_fltphp -= l_fltphp*l_flthp;
      sample = l_fltphp;

      // Phaser

      if(l_fphase || l_fdphase)
      {
        phaser_buffer[l_ipp&1023] = sample;
        sample += phaser_buffer[(l_ipp-l_iphase+1024)&1023];
        l_ipp = (l_ipp+1)&1023;
      }

      // Accumulate

      ssample += sample;
    }

    buffer[i] = ssample*l_env_vol*sound_vol*2/sp;
  }

  // Repeat

  rep_time = l_rep_time;

  // Arpeggio

  arp_time = l_arp_time;
  arp_limit = l_arp_limit;

  // Base

  phase = l_phase;
  period = l_period;
  fperiod = l_fperiod;
  fslide = l_fslide;

  // Square

  square_duty = l_square_duty;

  // Vibrato

  vib_phase = l_vib_phase;

  // Envelope

  env_time = l_env_time;
  env_stage = l_env_stage;

  // Noise

  fnoise = l_fnoise;
  ppnoise = l_ppnoise;

  // Phaser

  fphase = l_fphase;
  iphase = l_iphase;

  ipp = l_ipp;

  // Filter

  fltw = l_fltw;
  flthp = l_flthp;

  fltp = l_fltp;
  fltdp = l_fltdp;
  fltphp = l_fltphp;

  // Synth

  sampling = l_sampling;
}

//

void attachSampleToSound(Sample sample)
{
  Sound_SFXR.Sample = sample;
  Sound_SFXR.Length = sample.Length; // Set the Sound component length
}

//

void initSoundSample(int n)
{
  sound_vol = 0.5; // Important to set... this is not Sound_SFXR.Volume

  // Init sfxr parameters for the sound (this function is generated from Sheets)
  initSoundParam(n);

  float S = SampleLength(); // Get the sample length
  float L = S / 44100; // Get the sample length in seconds

  buffer.SizeDim1 = S + 1; // Set buffer size
  MySampleIndex = 0;

  Sample sample = getSampleName(n);
  sample.Length = L;
  sampleSize = S;

  //@RefreshContent(Component: sample); // This doesn't do anything? :-O
  attachSampleToSound(sample);
  @PlaySound(Sound: Sound_SFXR); // Sample needs(!) to be played to be generated ( lazy initialization i guess? )

  ResetSample(0); // Reset the synthesizer
  SynthSample(0,S,2); // Synthesize the entire sample in buffer

  @RefreshContent(Component:sample);
}]]>
      </Source>
    </ZLibrary>
    <SetAppState State="State_Init"/>
  </OnLoaded>
  <States>
    <AppState Name="State_Init" ModelUpdatesEnabled="0" CollisionsEnabled="0">
      <Definitions>
        <Variable Name="waitForSample" Type="4"/>
        <Variable Name="currentSoundNumber" Type="4"/>
        <Variable Name="sampleSize" Type="1"/>
      </Definitions>
      <OnStart>
        <ZExpression>
          <Expression>
<![CDATA[setRandomSeed(getSystemTime());

currentSoundNumber = 0;

Sound_SFXR.Volume = 0; // set volume to 0 during initialization]]>
          </Expression>
        </ZExpression>
      </OnStart>
      <OnUpdate>
        <ZExpression>
          <Expression>
<![CDATA[if (waitForSample == 0)
{
  waitForSample = 1;
  trace("Init Sound " + intToStr(currentSoundNumber));
  initSoundSample(currentSoundNumber);
}

if (waitForSample == 1)
{
  trace(intToStr(MySampleIndex) + "/" + intToStr(sampleSize));

  if(MySampleIndex >= sampleSize)
  {
    waitForSample = 0; // Stop waiting
    currentSoundNumber ++;

    if (currentSoundNumber == MAXSAMPLES)
    {
      Sound_SFXR.Volume = 0.25; // reset sound volume
      @SetAppState(State:Demo);
    }
  }
}]]>
          </Expression>
        </ZExpression>
      </OnUpdate>
    </AppState>
    <AppState Name="Demo">
      <OnUpdate>
        <KeyPress Comment="mouse click play sound" Keys="{" RepeatDelay="0.2">
          <OnPressed>
            <ZExpression>
              <Expression>
<![CDATA[int snd = floor(rnd() * MAXSAMPLES);

Sample sample = getSampleName(snd);
attachSampleToSound(sample);
@PlaySound(Sound:Sound_SFXR);
trace("Play sound " + intToStr(snd));]]>
              </Expression>
            </ZExpression>
          </OnPressed>
        </KeyPress>
      </OnUpdate>
    </AppState>
  </States>
  <Content>
    <Group Comment="SFXR">
      <Children>
        <Group Comment="Sample">
          <Children>
            <Group Comment="Synth">
              <Children>
                <Variable Name="sampling" Type="1"/>
                <Array Name="buffer" SizeDim1="22554"/>
              </Children>
            </Group>
            <Group Comment="Base">
              <Children>
                <Variable Name="phase"/>
                <Variable Name="period"/>
                <Variable Name="fperiod"/>
                <Variable Name="fmaxperiod"/>
                <Variable Name="fslide"/>
                <Variable Name="fdslide"/>
              </Children>
            </Group>
            <Group Comment="Square">
              <Children>
                <Variable Name="square_duty"/>
                <Variable Name="square_slide"/>
              </Children>
            </Group>
            <Group Comment="Vibrato">
              <Children>
                <Variable Name="vib_phase"/>
                <Variable Name="vib_speed"/>
                <Variable Name="vib_amp"/>
              </Children>
            </Group>
            <Group Comment="Envelope">
              <Children>
                <Variable Name="env_stage"/>
                <Variable Name="env_time"/>
                <Array Name="env_length" SizeDim1="3"/>
              </Children>
            </Group>
            <Group Comment="Filter">
              <Children>
                <Variable Name="fltp"/>
                <Variable Name="fltdp"/>
                <Variable Name="fltw"/>
                <Variable Name="fltw_d"/>
                <Variable Name="fltdmp"/>
                <Variable Name="fltphp"/>
                <Variable Name="flthp"/>
                <Variable Name="flthp_d"/>
              </Children>
            </Group>
            <Group Comment="Noise">
              <Children>
                <Variable Name="fnoise"/>
                <Variable Name="ppnoise" Type="1"/>
              </Children>
            </Group>
            <Group Comment="Phaser">
              <Children>
                <Variable Name="fphase"/>
                <Variable Name="fdphase"/>
                <Variable Name="iphase" Type="1"/>
                <Variable Name="ipp" Type="1"/>
                <Array Name="phaser_buffer" SizeDim1="1024"/>
              </Children>
            </Group>
            <Group Comment="Repeat">
              <Children>
                <Variable Name="rep_time"/>
                <Variable Name="rep_limit"/>
              </Children>
            </Group>
            <Group Comment="Arpeggio">
              <Children>
                <Variable Name="arp_time"/>
                <Variable Name="arp_mod"/>
                <Variable Name="arp_limit"/>
              </Children>
            </Group>
          </Children>
        </Group>
        <Group Comment="Parameters">
          <Children>
            <Group Comment="Base">
              <Children>
                <Variable Name="wave_type" Type="1"/>
                <Variable Name="sound_vol"/>
                <Variable Name="p_base_freq"/>
                <Variable Name="p_freq_limit"/>
                <Variable Name="p_freq_ramp"/>
                <Variable Name="p_freq_dramp"/>
              </Children>
            </Group>
            <Group Comment="Square">
              <Children>
                <Variable Name="p_duty"/>
                <Variable Name="p_duty_ramp"/>
              </Children>
            </Group>
            <Group Comment="Vibrato">
              <Children>
                <Variable Name="p_vib_speed"/>
                <Variable Name="p_vib_strength"/>
              </Children>
            </Group>
            <Group Comment="Envelope">
              <Children>
                <Variable Name="p_env_attack"/>
                <Variable Name="p_env_sustain"/>
                <Variable Name="p_env_decay"/>
                <Variable Name="p_env_punch"/>
              </Children>
            </Group>
            <Group Comment="Filter">
              <Children>
                <Variable Name="p_lpf_freq"/>
                <Variable Name="p_lpf_ramp"/>
                <Variable Name="p_lpf_resonance"/>
                <Variable Name="p_hpf_freq"/>
                <Variable Name="p_hpf_ramp"/>
              </Children>
            </Group>
            <Group Comment="Phaser">
              <Children>
                <Variable Name="p_pha_offset"/>
                <Variable Name="p_pha_ramp"/>
              </Children>
            </Group>
            <Group Comment="Repeat">
              <Children>
                <Variable Name="p_repeat_speed"/>
              </Children>
            </Group>
            <Group Comment="Arpeggio">
              <Children>
                <Variable Name="p_arp_speed"/>
                <Variable Name="p_arp_mod"/>
              </Children>
            </Group>
          </Children>
        </Group>
        <Variable Name="MySampleIndex" Type="1"/>
        <Sound Name="Sound_SFXR" Length="0.5114" Sample="Sample_Laser" SampleRepeatPosition="-1" UseSampleHz="255"/>
      </Children>
    </Group>
    <Sample Name="Sample_Explosion" Length="0.6778">
      <Producers>
        <SampleExpression Expression="this.Sample = buffer[MySampleIndex++];"/>
      </Producers>
    </Sample>
    <Sample Name="Sample_PowerUp" Length="0.636">
      <Producers>
        <SampleExpression Expression="this.Sample = buffer[MySampleIndex++];"/>
      </Producers>
    </Sample>
    <Sample Name="Sample_Laser" Length="0.5114">
      <Producers>
        <SampleExpression Expression="this.Sample = buffer[MySampleIndex++];"/>
      </Producers>
    </Sample>
  </Content>
</ZApplication>
I'm just wondering: I'm attaching the Sample to Sound_SFXR before playing them. So far, there haven't been any issues playing multiple sounds simultaneously. So, should I continue using a single Sound object for all Samples, or should I consider creating multiple Sound objects, one for each Sample?
Last edited by Ats on Mon May 06, 2024 10:16 pm, edited 2 times in total.
User avatar
Kjell
Posts: 1911
Joined: Sat Feb 23, 2008 11:15 pm

Re: SFXR

Post by Kjell »

Hi Ats,
Ats wrote: Sun May 05, 2024 12:45 pmI'm just wondering: I'm attaching the Sample to Sound_SFXR before playing them. So far, there haven't been any issues playing multiple sounds simultaneously. So, should I continue using a single Sound object for all Samples, or should I consider creating multiple Sound objects, one for each Sample?
You can do what you're doing and only use a single Sound component for all your samples .. as long as you don't enable PlaySound.ByReference.

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

Re: SFXR

Post by Ats »

Hello, I have a quick question: is it possible to declare a Sample using a ZLibrary instead of manually creating the Sample object? This would greatly simplify how I create sounds from my external spreadsheet.
I tried

Code: Select all

Sample Sample_Laser;
It doesn't throw error, but then it gets stuck during the initialization with an access violation error.
User avatar
Kjell
Posts: 1911
Joined: Sat Feb 23, 2008 11:15 pm

Re: SFXR

Post by Kjell »

Hi Ats,
Ats wrote: Wed Jun 12, 2024 10:35 amIs it possible to declare a Sample using a ZLibrary instead of manually creating the Sample object?
Yes, but maybe not in the way you expect?
Ats wrote: Wed Jun 12, 2024 10:35 amI tried "Sample Sample_Laser;"
This basically allocates a pointer to a Sample, nothing more. You could use "Sample mySample = @Sample(Length: 0.5);" to actually create a sample and assign it to the pointer variable, but that's not very useful either .. since without a SampleExpression component there's no way to access the Sample data.

What you can do however is use "meta" scripting, like this:

Code: Select all

Component mySample = createComponent(App, "Content", "Sample");
setStringProperty(mySample, "Name", "MySample");
setNumericProperty(mySample, "Length", 0, 0.5);

Component mySampleExpression = createComponent(MySample, "Producers", "SampleExpression");
setStringProperty(mySampleExpression, "Expression", "this.Sample = sin(this.Time*PI*440);");
Unfortunately there's no deleteComponent(), so you have to delete the created Samples by hand every time you want to re-import them :cry:

K
Post Reply