<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Probleme bei der Initialisierungsreihenfolge von globalen Objekten]]></title><description><![CDATA[<p>Hallo Leutz, wie der Titel schon verlauten lässt habe ich womöglich ein Probleme mit der Initialisierungsreihenfolge von Objekten bzw mit der Boot Prozedur der PS2.</p>
<p>Das Problem ist das der Audio Stream nicht triggert weil ein Semaphore hängt.<br />
Hier ist mal die komplette Audiostream.h</p>
<pre><code class="language-cpp">#ifndef AUDIOSTREAM_H
#define AUDIOSTREAM_H
#ifdef __cplusplus
#include &lt;cstdlib&gt;
#else
#include &lt;stdlib.h&gt;
#endif

#include &lt;stdio.h&gt;
#include &lt;kernel.h&gt;
#include &lt;tamtypes.h&gt;
#include &lt;cstdlib&gt; // für free
#include &lt;cstdint&gt;  // Für uint8_t, uint32_t
#include &lt;cstddef&gt;  // Für NULL
#include &lt;cstring&gt;  // Für memcpy

#define STACK_SIZE (32 * 1024)

// 1. WICHTIG: Konstante definieren, damit sie überall bekannt ist
#define AUDIO_BLOCK_SAMPLES 256
#define AUDIO_SAMPLE_RATE_EXACT 48000.0f
#define AUDIO_SAMPLE_RATE (int)(AUDIO_SAMPLE_RATE_EXACT)
#define MAX_AUDIO_MEMORY 6144
#define NUM_MASKS (((MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2) + 31) / 32)

// 2. Forward Declarations
class AudioStream;
class AudioConnection;

typedef struct audio_block_struct
{
    uint8_t  ref_count;
    uint16_t memory_pool_index;
    float    data[AUDIO_BLOCK_SAMPLES];
} audio_block_t;

class AudioConnection
{
public:
    AudioConnection();
    AudioConnection(AudioStream &amp;source, AudioStream &amp;destination)
        : AudioConnection()
    {
        connect(source,destination);
    }
    AudioConnection(AudioStream &amp;source, unsigned char sourceOutput,
                    AudioStream &amp;destination, unsigned char destinationInput)
        : AudioConnection()
    {
        connect(source,sourceOutput, destination,destinationInput);
    }
    friend class AudioStream;
    ~AudioConnection();
    int disconnect(void);
    int connect(void);
    int connect(AudioStream &amp;source, AudioStream &amp;destination)
    {
        return connect(source,0,destination,0);
    };
    int connect(AudioStream &amp;source, unsigned char sourceOutput,
                AudioStream &amp;destination, unsigned char destinationInput);

protected:
    AudioStream* src;
    AudioStream* dst;
    unsigned char src_index;
    unsigned char dest_index;
    AudioConnection *next_dest;
    bool isConnected;
};

class AudioStream
{
public:
    AudioStream(unsigned char ninput, audio_block_t **iqueue) :
        num_inputs(ninput), inputQueue(iqueue)
    {
        active = false;
        destination_list = NULL;
        for (int i=0; i &lt; num_inputs; i++)
        {
            inputQueue[i] = NULL;
        }
        // add to a simple list, for update_all
        // TODO: replace with a proper data flow analysis in update_all
        if (first_update == NULL)
        {
            first_update = this;
        }
        else
        {
            AudioStream *p;
            for (p=first_update; p-&gt;next_update; p = p-&gt;next_update) ;
            p-&gt;next_update = this;
        }
        next_update = NULL;
        numConnections = 0;
    }

    static void initialize_memory(audio_block_t *data, unsigned int num);
    static void AudioNoInterrupts()
    {
        update_exceptions++;
    }
    static void AudioInterrupts()
    {
        if (update_exceptions &gt; 0) update_exceptions--;
    }

protected:
    bool active;
    friend class AudioConnection;
    static audio_block_t * allocate(void);
    static void release(audio_block_t * block);
    void transmit(audio_block_t *block, unsigned char index = 0);
    audio_block_t * receiveReadOnly(unsigned int index = 0);
    audio_block_t * receiveWritable(unsigned int index = 0);
    static bool update_setup(void);
    static void update_stop(void);
    static void update_all(void)
    {
            printf(&quot;DEBUG: update_all check! audioSemaID ist: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);
        if(audioSemaID == -1 )return;
        SignalSema(audioSemaID);
    }
    uint8_t num_inputs;
    uint32_t numConnections;
    friend void software_isr(void* arg);
    friend u64 tick_cb(s32 id, u64 scheduled, u64 actual, void* arg, void* pc_val);

private:
    static AudioConnection* unused;
    audio_block_t **inputQueue;
    static AudioStream *first_update;
    AudioStream *next_update;
    AudioConnection *destination_list;
    virtual void update(void) = 0;
    static audio_block_t *memory_pool;
    static uint32_t memory_pool_available_mask[NUM_MASKS];
    static uint16_t memory_pool_first_mask;
    // Statistiken (optional)
    static uint16_t memory_used;
    static uint16_t memory_used_max;
    static volatile s32 audioSemaID;
    static bool update_scheduled;
    static u64 s_audio_ticks;
    static volatile uint32_t update_exceptions;
};

#define AudioMemory(num) ({ \
	static audio_block_t data[num]; \
	AudioStream::initialize_memory(data, num); \
})


#endif
</code></pre>
<p>AudioOutput:</p>
<pre><code class="language-cpp">#ifndef AUDIOOUTPUTSTREAM_H
#define AUDIOOUTPUTSTREAM_H
#ifdef __cplusplus
#include &lt;cstdlib&gt;
#else
#include &lt;stdlib.h&gt;
#endif
#include &lt;cstdint&gt;
#include &quot;AudioStream.h&quot;

#define CHUNK_SIZE 2048              // Bytes pro audsrv_play_audio Aufruf
#define RING_BUFFER_BLOCKS 8

class AudioOutputStream  : public AudioStream
{
public:
    AudioOutputStream(void) : AudioStream(2, inputQueueArray)
    {
        begin();
    }
    void begin(void);
    virtual void update(void);
    friend class AudioInputStream;

protected:
    static bool update_responsibility;
    friend int fillbuffer(void *arg);

private:
    static volatile int write_idx;
    static volatile int read_idx;
    static volatile int blocks_available;
    audio_block_t *inputQueueArray[2];
};

#endif // AUDIOOUTPUTSTREAM_H


int fillbuffer(void *arg)
{

/*
    u32 sec, usec;
    TimerBusClock2USec(GetTimerSystemTime(), &amp;sec, &amp;usec);
    u32 now =  usec;
    time_callback = now - last_time_callback;
    last_time_callback = now;
*/
    if(AudioOutputStream::update_responsibility)
    {
        AudioStream::update_all();
        AudioStream::update_all();
    }

    // Wir brauchen 2048 Bytes, also genau 2 Audio-Blöcke (2 x 1024 Bytes)
    if (AudioOutputStream::blocks_available &gt;= 2)
    {
        // Zeiger auf den aktuellen Startblock
        // (Da wir immer um 2 erhöhen, sind die nächsten 2048 Bytes garantiert am Stück im RAM)
        char *src_ptr = (char*)&amp;ring_buffer[AudioOutputStream::read_idx * AUDIO_BLOCK_SAMPLES * 2];

        // Ein einziger Aufruf für die vollen 2048 Bytes
        int played = audsrv_play_audio(src_ptr, CHUNK_SIZE);

        // audsrv_play_audio gibt die Anzahl der verarbeiteten Bytes zurück
        if (played &gt; 0)
        {
            // Lese-Index um 2 Blöcke weiterschieben
            AudioOutputStream::read_idx = (AudioOutputStream::read_idx + 2) % RING_BUFFER_BLOCKS;

            DI();
            AudioOutputStream::blocks_available -= 2;
            EI();
        }
    }
    else
    {
        audsrv_play_audio(silence, CHUNK_SIZE);
    }

    return 0;
}


void AudioOutputStream::begin()
{
    update_responsibility = update_setup();//this booting the IOP
    int ret;
    int err;
    printf(&quot;#Lade audsrv\n&quot;);
    #ifdef _DTL_T10000
     int modul_ret;

    ret = SifLoadModule(&quot;host:irx/libsd.irx&quot;, 0, NULL);
	printf(&quot;LIBSD loadmodule %d\n&quot;, ret);

    ret = SifLoadStartModule(&quot;host:irx/audsrv.irx&quot;, 0, NULL, &amp;modul_ret);
    printf(&quot;AUDSRV SifLoad_ret: %d Modul_ret: %d\n&quot;, ret, modul_ret);

    #else
    ret = SifLoadModule(&quot;rom0:LIBSD&quot;, 0, NULL);
    printf(&quot;libsd loadmodule %d\n&quot;, ret);

    ret = SifLoadModule(&quot;host:audsrv.irx&quot;, 0, NULL);
    printf(&quot;audsrv loadmodule %d\n&quot;, ret);
        #endif // _DTL_T10000

    ret = audsrv_init();
    if (ret != 0)
    {
        printf(&quot;failed to initialize audsrv\n&quot;);
        printf(&quot;audsrv returned error string: %s\n&quot;, audsrv_get_error_string());
        return;
    }
    struct audsrv_fmt_t format;
    format.bits = 16;
    format.freq = AUDIO_SAMPLE_RATE;
    format.channels = 2;
    err = audsrv_set_format(&amp;format);
    printf(&quot;set format returned %d\n&quot;, err);
    printf(&quot;audsrv returned error string: %s\n&quot;, audsrv_get_error_string());

    audsrv_set_volume(MAX_VOLUME);

    err = audsrv_on_fillbuf(CHUNK_SIZE, fillbuffer, NULL);
    if (err != AUDSRV_ERR_NOERROR)
    {
        printf(&quot;audsrv_on_fillbuf failed with err=%d\n&quot;, err);
    }
}

void AudioOutputStream::update()
{
/*
    u32 sec, usec;
    TimerBusClock2USec(GetTimerSystemTime(), &amp;sec, &amp;usec);
    u32 now =  usec;
    printf(&quot;Intervall update: %d\n&quot;,now - last_time_update);
    last_time_update = now;
    printf(&quot;Intervall callback: %d\n&quot;, time_callback);

*/
printf(&quot;AudioOutputStream::update()\n&quot;);

    // 1. Check auf Buffer Overflow (optional, aber empfohlen)
    if (blocks_available &gt;= RING_BUFFER_BLOCKS) return;
</code></pre>
<p>In der main.cpp instanziiere ich globale Objecte.<br />
AudioSynthWaveformSine sine1;<br />
//AudioInputStream audioIn;<br />
AudioOutputStream audioOut;<br />
Audio_fftr  FFT;</p>
<p>AudioConnection patchCord0(sine1, 0, audioOut, 0);<br />
AudioConnection patchCord1(sine1, 0, audioOut, 1);<br />
AudioConnection patchCord2(sine1, 0, FFT, 0);</p>
<p>und in der main Funktion kommt irwann erst<br />
AudioMemory(32);<br />
das widerum  feuert void AudioStream::initialize_memory(audio_block_t *data, unsigned int num)</p>
<pre><code class="language-cpp">#include &quot;AudioStream.h&quot;
#include &lt;timer.h&gt;
#include &lt;stdio.h&gt;
#include &quot;IOP_BOOT.h&quot;

audio_block_t * AudioStream::memory_pool;
uint32_t AudioStream::memory_pool_available_mask[NUM_MASKS];
uint16_t AudioStream::memory_pool_first_mask;

bool AudioStream::update_scheduled = false;
uint16_t AudioStream::memory_used = 0;
uint16_t AudioStream::memory_used_max = 0;
AudioConnection* AudioStream::unused = NULL;
AudioStream * AudioStream::first_update = NULL;
static u8 threadStack[STACK_SIZE] __attribute__((aligned(16)));
volatile s32 AudioStream::audioSemaID = -1;
u64 AudioStream::s_audio_ticks = 0;
volatile uint32_t AudioStream::update_exceptions = 0;


void software_isr(void* arg)
{
    while(1)
    {
        // 1. Der Thread wartet IMMER auf den Timer
        WaitSema(AudioStream::audioSemaID);
        // 2. Nur wenn keine Sperre vorliegt, wird gerechnet
        if (AudioStream::update_exceptions == 0)
        {
            AudioStream *p;
            for (p = AudioStream::first_update; p; p = p-&gt;next_update)
            {
                if (p-&gt;active) p-&gt;update();
            }
        }
        EE_SYNC();

    }
}

// Die Signatur entspricht exakt deinem typedef
u64 tick_cb(s32 id, u64 scheduled, u64 actual, void* arg, void* pc_val)
{
    // Signal an die Semaphore
    iSignalSema(AudioStream::audioSemaID);
    // WICHTIG: Damit es ein Intervall bleibt, geben wir den nächsten
    // Zeitpunkt basierend auf der GEPLANTEN Zeit zurück.
    // Das verhindert, dass sich kleine Verzögerungen aufsummieren (Drift).
    return AudioStream::s_audio_ticks;
}

void AudioStream::initialize_memory(audio_block_t *data, unsigned int num)
{
    unsigned int i;
    unsigned int maxnum = MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2;
    if (num &gt; maxnum) num = maxnum;

    // --- START CRITICAL SECTION ---
    DI();
    memory_pool = data;
    memory_pool_first_mask = 0;
    for (i=0; i &lt; NUM_MASKS; i++)
    {
        memory_pool_available_mask[i] = 0;
    }
    for (i=0; i &lt; num; i++)
    {
        memory_pool_available_mask[i &gt;&gt; 5] |= (1 &lt;&lt; (i &amp; 0x1F));
    }
    for (i=0; i &lt; num; i++)
    {
        data[i].memory_pool_index = i;
    }
    EI();
    // --- END CRITICAL SECTION ---

    // Ab hier sind Interrupts wieder an. Kernel-Calls sind jetzt sicher!

    ee_sema_t audioSema;
    memset(&amp;audioSema, 0, sizeof(audioSema));
    audioSema.init_count = 0;
    audioSema.max_count = 3;
    audioSema.option = 0;
    audioSemaID = CreateSema(&amp;audioSema);
    printf(&quot;DEBUG: Frisch erstellt! audioSemaID ist jetzt: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);
    fflush(stdout);

    ee_thread_t threadParam;
    memset(&amp;threadParam, 0, sizeof(threadParam));
    threadParam.func = (void*)software_isr;
    threadParam.stack = threadStack;
    threadParam.stack_size = STACK_SIZE;
    threadParam.gp_reg = &amp;_gp; // Global Pointer der EE
    threadParam.initial_priority = 10; // Hohe Priorität als Main 16
    s32 threadID = CreateThread(&amp;threadParam);
    StartThread(threadID, NULL);

    printf(&quot;::initialize_memory %d\n&quot;, update_scheduled);

    if (update_scheduled == false)
    {
        update_setup();
        float usec = 1e6 * AUDIO_BLOCK_SAMPLES / AUDIO_SAMPLE_RATE_EXACT;
        s_audio_ticks = USec2TimerBusClock(usec);
        s32 id = AllocTimerCounter();
        SetTimerHandler(id,  s_audio_ticks, tick_cb, &amp;s_audio_ticks);
        StartTimerCounter(id);
    }
}
</code></pre>
<p>Die Sache ist nun das zuerst die globalen Objekte erstellt werden, das widerum feuert<br />
void AudioOutputStream::begin()<br />
{<br />
update_responsibility = update_setup();//this booting the IOP</p>
<p>damit hällt AudioOutputStream die update_responsibility<br />
fillbuffer feuert ab jetzt  AudioStream::update_all();</p>
<p>und hier geht es nicht weiter  '</p>
<pre><code class="language-cpp">static void update_all(void)
    {
            //printf(&quot;DEBUG: update_all check! audioSemaID ist: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);
        if(audioSemaID == -1 )return;
        SignalSema(audioSemaID);
    }
</code></pre>
<p>if(audioSemaID == -1 ) wird nie true bzw false im dem Fall.<br />
initialize_memory wird aufgerufen wenn auch etwas später<br />
weil ich sehe ja diese Ausgabe:<br />
ee_sema_t audioSema;<br />
memset(&amp;audioSema, 0, sizeof(audioSema));<br />
audioSema.init_count = 0;<br />
audioSema.max_count = 3;<br />
audioSema.option = 0;<br />
audioSemaID = CreateSema(&amp;audioSema);<br />
printf(&quot;DEBUG: Frisch erstellt! audioSemaID ist jetzt: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);<br />
fflush(stdout);</p>
<p>Die einzige logische Idee, die ich habe ist, es gibt zwei instanzen von audioSemaID<br />
Leider kann ich die Speicheradressen nicht ausgeben<br />
soballt printf in static void update_all(void) feuert wird das print in<br />
initialize_memory verschluckt.</p>
<p>Das Passiert weil die Ausgaben über den IOP laufen und wenn man da in eienr Schleife zu oft Ausgaben macht, geht das ein oder ander unter.<br />
Vorallem wenn man mit zwei Threads auf dem EE ausgaben machnen will. Das ist ein Nerviges Problem bei der Playstation 2.</p>
<p>Ich habe noch einen älteren Code wo ich noch keine Bildausgabe habe, da funktioert das audio. Das erklärt aber nicht weshalb audioSemaID nie &gt; -1 wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/355501/probleme-bei-der-initialisierungsreihenfolge-von-globalen-objekten</link><generator>RSS for Node</generator><lastBuildDate>Sun, 18 Oct 2026 15:46:11 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/355501.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 18 Oct 2026 14:10:32 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Probleme bei der Initialisierungsreihenfolge von globalen Objekten on Sun, 18 Oct 2026 14:10:32 GMT]]></title><description><![CDATA[<p>Hallo Leutz, wie der Titel schon verlauten lässt habe ich womöglich ein Probleme mit der Initialisierungsreihenfolge von Objekten bzw mit der Boot Prozedur der PS2.</p>
<p>Das Problem ist das der Audio Stream nicht triggert weil ein Semaphore hängt.<br />
Hier ist mal die komplette Audiostream.h</p>
<pre><code class="language-cpp">#ifndef AUDIOSTREAM_H
#define AUDIOSTREAM_H
#ifdef __cplusplus
#include &lt;cstdlib&gt;
#else
#include &lt;stdlib.h&gt;
#endif

#include &lt;stdio.h&gt;
#include &lt;kernel.h&gt;
#include &lt;tamtypes.h&gt;
#include &lt;cstdlib&gt; // für free
#include &lt;cstdint&gt;  // Für uint8_t, uint32_t
#include &lt;cstddef&gt;  // Für NULL
#include &lt;cstring&gt;  // Für memcpy

#define STACK_SIZE (32 * 1024)

// 1. WICHTIG: Konstante definieren, damit sie überall bekannt ist
#define AUDIO_BLOCK_SAMPLES 256
#define AUDIO_SAMPLE_RATE_EXACT 48000.0f
#define AUDIO_SAMPLE_RATE (int)(AUDIO_SAMPLE_RATE_EXACT)
#define MAX_AUDIO_MEMORY 6144
#define NUM_MASKS (((MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2) + 31) / 32)

// 2. Forward Declarations
class AudioStream;
class AudioConnection;

typedef struct audio_block_struct
{
    uint8_t  ref_count;
    uint16_t memory_pool_index;
    float    data[AUDIO_BLOCK_SAMPLES];
} audio_block_t;

class AudioConnection
{
public:
    AudioConnection();
    AudioConnection(AudioStream &amp;source, AudioStream &amp;destination)
        : AudioConnection()
    {
        connect(source,destination);
    }
    AudioConnection(AudioStream &amp;source, unsigned char sourceOutput,
                    AudioStream &amp;destination, unsigned char destinationInput)
        : AudioConnection()
    {
        connect(source,sourceOutput, destination,destinationInput);
    }
    friend class AudioStream;
    ~AudioConnection();
    int disconnect(void);
    int connect(void);
    int connect(AudioStream &amp;source, AudioStream &amp;destination)
    {
        return connect(source,0,destination,0);
    };
    int connect(AudioStream &amp;source, unsigned char sourceOutput,
                AudioStream &amp;destination, unsigned char destinationInput);

protected:
    AudioStream* src;
    AudioStream* dst;
    unsigned char src_index;
    unsigned char dest_index;
    AudioConnection *next_dest;
    bool isConnected;
};

class AudioStream
{
public:
    AudioStream(unsigned char ninput, audio_block_t **iqueue) :
        num_inputs(ninput), inputQueue(iqueue)
    {
        active = false;
        destination_list = NULL;
        for (int i=0; i &lt; num_inputs; i++)
        {
            inputQueue[i] = NULL;
        }
        // add to a simple list, for update_all
        // TODO: replace with a proper data flow analysis in update_all
        if (first_update == NULL)
        {
            first_update = this;
        }
        else
        {
            AudioStream *p;
            for (p=first_update; p-&gt;next_update; p = p-&gt;next_update) ;
            p-&gt;next_update = this;
        }
        next_update = NULL;
        numConnections = 0;
    }

    static void initialize_memory(audio_block_t *data, unsigned int num);
    static void AudioNoInterrupts()
    {
        update_exceptions++;
    }
    static void AudioInterrupts()
    {
        if (update_exceptions &gt; 0) update_exceptions--;
    }

protected:
    bool active;
    friend class AudioConnection;
    static audio_block_t * allocate(void);
    static void release(audio_block_t * block);
    void transmit(audio_block_t *block, unsigned char index = 0);
    audio_block_t * receiveReadOnly(unsigned int index = 0);
    audio_block_t * receiveWritable(unsigned int index = 0);
    static bool update_setup(void);
    static void update_stop(void);
    static void update_all(void)
    {
            printf(&quot;DEBUG: update_all check! audioSemaID ist: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);
        if(audioSemaID == -1 )return;
        SignalSema(audioSemaID);
    }
    uint8_t num_inputs;
    uint32_t numConnections;
    friend void software_isr(void* arg);
    friend u64 tick_cb(s32 id, u64 scheduled, u64 actual, void* arg, void* pc_val);

private:
    static AudioConnection* unused;
    audio_block_t **inputQueue;
    static AudioStream *first_update;
    AudioStream *next_update;
    AudioConnection *destination_list;
    virtual void update(void) = 0;
    static audio_block_t *memory_pool;
    static uint32_t memory_pool_available_mask[NUM_MASKS];
    static uint16_t memory_pool_first_mask;
    // Statistiken (optional)
    static uint16_t memory_used;
    static uint16_t memory_used_max;
    static volatile s32 audioSemaID;
    static bool update_scheduled;
    static u64 s_audio_ticks;
    static volatile uint32_t update_exceptions;
};

#define AudioMemory(num) ({ \
	static audio_block_t data[num]; \
	AudioStream::initialize_memory(data, num); \
})


#endif
</code></pre>
<p>AudioOutput:</p>
<pre><code class="language-cpp">#ifndef AUDIOOUTPUTSTREAM_H
#define AUDIOOUTPUTSTREAM_H
#ifdef __cplusplus
#include &lt;cstdlib&gt;
#else
#include &lt;stdlib.h&gt;
#endif
#include &lt;cstdint&gt;
#include &quot;AudioStream.h&quot;

#define CHUNK_SIZE 2048              // Bytes pro audsrv_play_audio Aufruf
#define RING_BUFFER_BLOCKS 8

class AudioOutputStream  : public AudioStream
{
public:
    AudioOutputStream(void) : AudioStream(2, inputQueueArray)
    {
        begin();
    }
    void begin(void);
    virtual void update(void);
    friend class AudioInputStream;

protected:
    static bool update_responsibility;
    friend int fillbuffer(void *arg);

private:
    static volatile int write_idx;
    static volatile int read_idx;
    static volatile int blocks_available;
    audio_block_t *inputQueueArray[2];
};

#endif // AUDIOOUTPUTSTREAM_H


int fillbuffer(void *arg)
{

/*
    u32 sec, usec;
    TimerBusClock2USec(GetTimerSystemTime(), &amp;sec, &amp;usec);
    u32 now =  usec;
    time_callback = now - last_time_callback;
    last_time_callback = now;
*/
    if(AudioOutputStream::update_responsibility)
    {
        AudioStream::update_all();
        AudioStream::update_all();
    }

    // Wir brauchen 2048 Bytes, also genau 2 Audio-Blöcke (2 x 1024 Bytes)
    if (AudioOutputStream::blocks_available &gt;= 2)
    {
        // Zeiger auf den aktuellen Startblock
        // (Da wir immer um 2 erhöhen, sind die nächsten 2048 Bytes garantiert am Stück im RAM)
        char *src_ptr = (char*)&amp;ring_buffer[AudioOutputStream::read_idx * AUDIO_BLOCK_SAMPLES * 2];

        // Ein einziger Aufruf für die vollen 2048 Bytes
        int played = audsrv_play_audio(src_ptr, CHUNK_SIZE);

        // audsrv_play_audio gibt die Anzahl der verarbeiteten Bytes zurück
        if (played &gt; 0)
        {
            // Lese-Index um 2 Blöcke weiterschieben
            AudioOutputStream::read_idx = (AudioOutputStream::read_idx + 2) % RING_BUFFER_BLOCKS;

            DI();
            AudioOutputStream::blocks_available -= 2;
            EI();
        }
    }
    else
    {
        audsrv_play_audio(silence, CHUNK_SIZE);
    }

    return 0;
}


void AudioOutputStream::begin()
{
    update_responsibility = update_setup();//this booting the IOP
    int ret;
    int err;
    printf(&quot;#Lade audsrv\n&quot;);
    #ifdef _DTL_T10000
     int modul_ret;

    ret = SifLoadModule(&quot;host:irx/libsd.irx&quot;, 0, NULL);
	printf(&quot;LIBSD loadmodule %d\n&quot;, ret);

    ret = SifLoadStartModule(&quot;host:irx/audsrv.irx&quot;, 0, NULL, &amp;modul_ret);
    printf(&quot;AUDSRV SifLoad_ret: %d Modul_ret: %d\n&quot;, ret, modul_ret);

    #else
    ret = SifLoadModule(&quot;rom0:LIBSD&quot;, 0, NULL);
    printf(&quot;libsd loadmodule %d\n&quot;, ret);

    ret = SifLoadModule(&quot;host:audsrv.irx&quot;, 0, NULL);
    printf(&quot;audsrv loadmodule %d\n&quot;, ret);
        #endif // _DTL_T10000

    ret = audsrv_init();
    if (ret != 0)
    {
        printf(&quot;failed to initialize audsrv\n&quot;);
        printf(&quot;audsrv returned error string: %s\n&quot;, audsrv_get_error_string());
        return;
    }
    struct audsrv_fmt_t format;
    format.bits = 16;
    format.freq = AUDIO_SAMPLE_RATE;
    format.channels = 2;
    err = audsrv_set_format(&amp;format);
    printf(&quot;set format returned %d\n&quot;, err);
    printf(&quot;audsrv returned error string: %s\n&quot;, audsrv_get_error_string());

    audsrv_set_volume(MAX_VOLUME);

    err = audsrv_on_fillbuf(CHUNK_SIZE, fillbuffer, NULL);
    if (err != AUDSRV_ERR_NOERROR)
    {
        printf(&quot;audsrv_on_fillbuf failed with err=%d\n&quot;, err);
    }
}

void AudioOutputStream::update()
{
/*
    u32 sec, usec;
    TimerBusClock2USec(GetTimerSystemTime(), &amp;sec, &amp;usec);
    u32 now =  usec;
    printf(&quot;Intervall update: %d\n&quot;,now - last_time_update);
    last_time_update = now;
    printf(&quot;Intervall callback: %d\n&quot;, time_callback);

*/
printf(&quot;AudioOutputStream::update()\n&quot;);

    // 1. Check auf Buffer Overflow (optional, aber empfohlen)
    if (blocks_available &gt;= RING_BUFFER_BLOCKS) return;
</code></pre>
<p>In der main.cpp instanziiere ich globale Objecte.<br />
AudioSynthWaveformSine sine1;<br />
//AudioInputStream audioIn;<br />
AudioOutputStream audioOut;<br />
Audio_fftr  FFT;</p>
<p>AudioConnection patchCord0(sine1, 0, audioOut, 0);<br />
AudioConnection patchCord1(sine1, 0, audioOut, 1);<br />
AudioConnection patchCord2(sine1, 0, FFT, 0);</p>
<p>und in der main Funktion kommt irwann erst<br />
AudioMemory(32);<br />
das widerum  feuert void AudioStream::initialize_memory(audio_block_t *data, unsigned int num)</p>
<pre><code class="language-cpp">#include &quot;AudioStream.h&quot;
#include &lt;timer.h&gt;
#include &lt;stdio.h&gt;
#include &quot;IOP_BOOT.h&quot;

audio_block_t * AudioStream::memory_pool;
uint32_t AudioStream::memory_pool_available_mask[NUM_MASKS];
uint16_t AudioStream::memory_pool_first_mask;

bool AudioStream::update_scheduled = false;
uint16_t AudioStream::memory_used = 0;
uint16_t AudioStream::memory_used_max = 0;
AudioConnection* AudioStream::unused = NULL;
AudioStream * AudioStream::first_update = NULL;
static u8 threadStack[STACK_SIZE] __attribute__((aligned(16)));
volatile s32 AudioStream::audioSemaID = -1;
u64 AudioStream::s_audio_ticks = 0;
volatile uint32_t AudioStream::update_exceptions = 0;


void software_isr(void* arg)
{
    while(1)
    {
        // 1. Der Thread wartet IMMER auf den Timer
        WaitSema(AudioStream::audioSemaID);
        // 2. Nur wenn keine Sperre vorliegt, wird gerechnet
        if (AudioStream::update_exceptions == 0)
        {
            AudioStream *p;
            for (p = AudioStream::first_update; p; p = p-&gt;next_update)
            {
                if (p-&gt;active) p-&gt;update();
            }
        }
        EE_SYNC();

    }
}

// Die Signatur entspricht exakt deinem typedef
u64 tick_cb(s32 id, u64 scheduled, u64 actual, void* arg, void* pc_val)
{
    // Signal an die Semaphore
    iSignalSema(AudioStream::audioSemaID);
    // WICHTIG: Damit es ein Intervall bleibt, geben wir den nächsten
    // Zeitpunkt basierend auf der GEPLANTEN Zeit zurück.
    // Das verhindert, dass sich kleine Verzögerungen aufsummieren (Drift).
    return AudioStream::s_audio_ticks;
}

void AudioStream::initialize_memory(audio_block_t *data, unsigned int num)
{
    unsigned int i;
    unsigned int maxnum = MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2;
    if (num &gt; maxnum) num = maxnum;

    // --- START CRITICAL SECTION ---
    DI();
    memory_pool = data;
    memory_pool_first_mask = 0;
    for (i=0; i &lt; NUM_MASKS; i++)
    {
        memory_pool_available_mask[i] = 0;
    }
    for (i=0; i &lt; num; i++)
    {
        memory_pool_available_mask[i &gt;&gt; 5] |= (1 &lt;&lt; (i &amp; 0x1F));
    }
    for (i=0; i &lt; num; i++)
    {
        data[i].memory_pool_index = i;
    }
    EI();
    // --- END CRITICAL SECTION ---

    // Ab hier sind Interrupts wieder an. Kernel-Calls sind jetzt sicher!

    ee_sema_t audioSema;
    memset(&amp;audioSema, 0, sizeof(audioSema));
    audioSema.init_count = 0;
    audioSema.max_count = 3;
    audioSema.option = 0;
    audioSemaID = CreateSema(&amp;audioSema);
    printf(&quot;DEBUG: Frisch erstellt! audioSemaID ist jetzt: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);
    fflush(stdout);

    ee_thread_t threadParam;
    memset(&amp;threadParam, 0, sizeof(threadParam));
    threadParam.func = (void*)software_isr;
    threadParam.stack = threadStack;
    threadParam.stack_size = STACK_SIZE;
    threadParam.gp_reg = &amp;_gp; // Global Pointer der EE
    threadParam.initial_priority = 10; // Hohe Priorität als Main 16
    s32 threadID = CreateThread(&amp;threadParam);
    StartThread(threadID, NULL);

    printf(&quot;::initialize_memory %d\n&quot;, update_scheduled);

    if (update_scheduled == false)
    {
        update_setup();
        float usec = 1e6 * AUDIO_BLOCK_SAMPLES / AUDIO_SAMPLE_RATE_EXACT;
        s_audio_ticks = USec2TimerBusClock(usec);
        s32 id = AllocTimerCounter();
        SetTimerHandler(id,  s_audio_ticks, tick_cb, &amp;s_audio_ticks);
        StartTimerCounter(id);
    }
}
</code></pre>
<p>Die Sache ist nun das zuerst die globalen Objekte erstellt werden, das widerum feuert<br />
void AudioOutputStream::begin()<br />
{<br />
update_responsibility = update_setup();//this booting the IOP</p>
<p>damit hällt AudioOutputStream die update_responsibility<br />
fillbuffer feuert ab jetzt  AudioStream::update_all();</p>
<p>und hier geht es nicht weiter  '</p>
<pre><code class="language-cpp">static void update_all(void)
    {
            //printf(&quot;DEBUG: update_all check! audioSemaID ist: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);
        if(audioSemaID == -1 )return;
        SignalSema(audioSemaID);
    }
</code></pre>
<p>if(audioSemaID == -1 ) wird nie true bzw false im dem Fall.<br />
initialize_memory wird aufgerufen wenn auch etwas später<br />
weil ich sehe ja diese Ausgabe:<br />
ee_sema_t audioSema;<br />
memset(&amp;audioSema, 0, sizeof(audioSema));<br />
audioSema.init_count = 0;<br />
audioSema.max_count = 3;<br />
audioSema.option = 0;<br />
audioSemaID = CreateSema(&amp;audioSema);<br />
printf(&quot;DEBUG: Frisch erstellt! audioSemaID ist jetzt: %d (Adresse: %p)\n&quot;, audioSemaID, (void*)&amp;audioSemaID);<br />
fflush(stdout);</p>
<p>Die einzige logische Idee, die ich habe ist, es gibt zwei instanzen von audioSemaID<br />
Leider kann ich die Speicheradressen nicht ausgeben<br />
soballt printf in static void update_all(void) feuert wird das print in<br />
initialize_memory verschluckt.</p>
<p>Das Passiert weil die Ausgaben über den IOP laufen und wenn man da in eienr Schleife zu oft Ausgaben macht, geht das ein oder ander unter.<br />
Vorallem wenn man mit zwei Threads auf dem EE ausgaben machnen will. Das ist ein Nerviges Problem bei der Playstation 2.</p>
<p>Ich habe noch einen älteren Code wo ich noch keine Bildausgabe habe, da funktioert das audio. Das erklärt aber nicht weshalb audioSemaID nie &gt; -1 wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2625344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2625344</guid><dc:creator><![CDATA[D_Key]]></dc:creator><pubDate>Sun, 18 Oct 2026 14:10:32 GMT</pubDate></item><item><title><![CDATA[Reply to Probleme bei der Initialisierungsreihenfolge von globalen Objekten on Sun, 18 Oct 2026 15:19:20 GMT]]></title><description><![CDATA[<p>Ich habe ein paar formelle Anmerkungen:</p>
<ul>
<li>Der Code ist weiten teils nicht richtig eingerückt bzw. formatiert.</li>
</ul>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/38719">@D_Key</a> sagte in <a href="/forum/post/2625344">Probleme bei der Initialisierungsreihenfolge von globalen Objekten</a>:</p>
<blockquote>
<p>Objecte</p>
</blockquote>
<ul>
<li>Entweder Englisch (Objects) oder Deutsch (Objekte), aber nicht beides mixen.</li>
</ul>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/38719">@D_Key</a> sagte in <a href="/forum/post/2625344">Probleme bei der Initialisierungsreihenfolge von globalen Objekten</a>:</p>
<blockquote>
<p>PS2</p>
</blockquote>
<ul>
<li>Damit kenne ich mich leider nicht aus, aber hast du mal die KI gefragt? Prädestiniert dafür...</li>
</ul>
<p>Nur überflogen: Vermutlich gibt es einen Mutex-Lock (RAII) irgendwo.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2625345</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2625345</guid><dc:creator><![CDATA[Anon-81275]]></dc:creator><pubDate>Sun, 18 Oct 2026 15:19:20 GMT</pubDate></item><item><title><![CDATA[Reply to Probleme bei der Initialisierungsreihenfolge von globalen Objekten on Sun, 18 Oct 2026 15:38:25 GMT]]></title><description><![CDATA[<p>Jo, Race Conditions ... <a href="https://share.google/aimode/8Ri2k2s1jHnqyTZLI" rel="nofollow">https://share.google/aimode/8Ri2k2s1jHnqyTZLI</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2625346</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2625346</guid><dc:creator><![CDATA[Anon-81275]]></dc:creator><pubDate>Sun, 18 Oct 2026 15:38:25 GMT</pubDate></item></channel></rss>