#ELSE

ポイズン雷花poison_raika
2026-02-09
サファイア・ネオsapphire_neo@mastodon.world
2026-02-07
ポイズン雷花poison_raika
2026-02-07

@shugo gcc -EするとNULLが/usr/lib/gcc/x86_64-linux-gnu/13/include/stddef.hでdefineされていることがわかって、下記のように、Cなら(void *)に、C++なら整数になるみたいです。

:
#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else /* C++ */
#define NULL 0
#endif /* C++ */
#endif /* G++ */
#endif /* NULL not defined and <stddef.h> or need NULL. */
#undef __need_NULL
:

2026-01-24

update: I did, that works great.

but also, I really had to bite the bullet and parse #ifdef #else etc. so now I have a little stack machine set up.

2026-01-21

@draeand I don't even think it used the docs lol. For the record, if you're curious: // Prism state
#ifdef USE_PRISM
static PrismContext* g_prismCtx = nullptr;
static PrismBackend* g_prismBackend = nullptr;
#endif

Then, // Screen reader output - uses async message to avoid blocking UI
#ifdef USE_PRISM
static std::string g_pendingSpeech;
static bool g_speechInterrupt = true;

void DoSpeak() {
if (g_prismBackend && !g_pendingSpeech.empty()) {
prism_backend_output(g_prismBackend, g_pendingSpeech.c_str(), g_speechInterrupt);
g_pendingSpeech.clear();
}
}

void Speak(const char* text, bool interrupt = true) {
if (g_prismBackend && g_hwnd) {
g_pendingSpeech = text;
g_speechInterrupt = interrupt;
PostMessage(g_hwnd, WM_SPEAK, 0, 0);
}
}

void Speak(const std::string& text, bool interrupt = true) {
Speak(text.c_str(), interrupt);
}
#else
void DoSpeak() {}
void Speak(const char*, bool = true) {}
void Speak(const std::string&, bool = true) {}
#endif

and in the init funcs: // Initialize Prism for screen reader support
#ifdef USE_PRISM
bool InitPrism(HWND hwnd) {
PrismConfig cfg = prism_config_init();
cfg.hwnd = hwnd;

g_prismCtx = prism_init(&cfg);
if (!g_prismCtx) {
return false;
}

g_prismBackend = prism_registry_acquire_best(g_prismCtx);
if (!g_prismBackend) {
return false;
}

PrismError err = prism_backend_initialize(g_prismBackend);
if (err != PRISM_OK) {
return false;
}

return true;
}

// Shutdown Prism
void FreePrism() {
if (g_prismBackend) {
prism_backend_free(g_prismBackend);
g_prismBackend = nullptr;
}
if (g_prismCtx) {
prism_shutdown(g_prismCtx);
g_prismCtx = nullptr;
}
}
#else
bool InitPrism(HWND) { return false; }
void FreePrism() {}
#endif

2026-01-17
@kabel42 error messages for macros are tame until people start abusing macros and specially N layer macros that each is conditional and holy i hate that

but imo a simple `#ifdef PLATFORM_A /* some code for pa */ #else /* some fallback code */` is usually just fine
2026-01-16

@bagder does that include #else/#elif as well?

サファイア・ネオsapphire_neo@mastodon.world
2026-01-10
サファイア・ネオsapphire_neo@mastodon.world
2026-01-09
Fringe Fictionfringefiction
2026-01-05

Fringe Fiction Goes to the Movies  

Over this cold weekend in Philadelphia, Fringe Fiction did get to watch a couple of movies: Else and Tarot. Else and Tarot are both worth a watch, but Else is the more interesting fare. Else is an interesting foreign movie where inanimate objects is merging with humanity. It is not quite body horror, and it does lean toward the artistic side, particularly toward the…

fringefiction.me/2026/01/04/fr

2025-12-31

Start recording for 2026 Winter #Anime 📺 #Book 📕 #Comics 💬 #Movie🎦 #Videogames 🎮 #Else🃏

네프요나nepu47@planet.moe
2025-12-31

Start recording for 2026 Winter
#Anime 📺
#Book 📕
#Comics 💬
#Movie🎦
#Videogames 🎮
#Else🃏

bcm2835_vcaudio.c で

sc->sc_format.encoding = AUDIO_ENCODING_SLINEAR_LE;

のまま

vcaudio_swvol_codec()

*dst++ = htole16((aint_t)v);
とBEのときだけひっくり返すのか、

#if BYTE_ORDER == BIG_ENDIAN
sc->sc_format.encoding = AUDIO_ENCODING_SLINEAR_BE;
#else
sc->sc_format.encoding = AUDIO_ENCODING_SLINEAR_LE;
#endif

とすべきなのか

Gareth Lloyd (He/him)glloyd@fosstodon.org
2025-12-18

#if DECLARE_CONSTEXPR
template<typename T>
constexpr int f1(); // works
#else
template<typename T>
inline int f1(); // also works
#endif

template<>
constexpr int f1<int>(){ return 1;}

static int global = 2;
template<>
inline int f1<double>(){ return global;}

constexpr int f2(); // here declaration must match definition
constexpr int f2() { return 3; }

int main() {
constexpr auto v1 = f1<int>();
auto const v2 = f1<double>();
auto const v3 = f2();
return v1 + v2 + v3;
}

Comment mettre de la couleur dans votre #raytracing de la famille Hexacone..

#local R  = rand(Rng1);
#if 	(R < 0.25)	texture { tPlasticOrange }
#elseif	(R < 0.50)	texture { tPlasticBlue   }
#elseif	(R < 0.75)	texture { tPlasticPrune  }
#else 			texture { tPlasticGreen  }
#end	// if

#Povray, c'est trop cool !

ATtiny85 MIDI to CV

There are a number of projects out there that provide a MIDI to CV function utilising some flavour of the ATtiny family of microcontrollers.  But most of them go from USB MIDI to CV but I wanted a genuine 5-pin DIN MIDI to CV.  This was the result.

It has taken a basic MIDI in circuit from the Internet (Google will find a few of these kicking around) and pairs it with the ATtiny85 CV out section of Jan Ostman’s cheap USB MIDI 2 CV design (Jan Ostman’s site is no more so I can’t link to it anymore).

The result is as follows.

Update 2025: if you’d like to have this in a module you can just buy and use, take a look at https://lectronz.com/products/midi-to-cv.  Note: I don’t have this, and have no connection with it, I’m just passing this on as I saw it was essentially the same circuit and thought it might be useful!

Update July 2021: Added a TRIGGER output on Pin 5.

I also have a version for the ATtiny2313, but the main changes are as you’d expect.  Basically I was having problems with the ATtiny85 missing MIDI messages and wondered if a hardware UART would be better.  Turned out it was just my dodgy code with no real error checking getting out of sync with the MIDI stream.  But it took trying it on a 2313 to highlight the real issue, so back to the ATtiny85 and now all is well.

Design wise, its fairly simple ATtiny85 wise with the pin usage as follows:

  • SoftwareSerial receive on D3 (PB3) which is physical pin 2.
  • Gate output on D2 (PB2) which is physical pin 7.
  • CV output using the PWM signal tied to OC1A triggered off timer 1, which is D1 (PB1) on physical pin 6.
  • Update July 21: Trigger output on D0 (PB0) which is physical pin 5.

The code uses the same trick that Jan Ostman used in his code – if the top compare value for PWM operation is 239 then there are 240 graduations for PWM.  To cover a MIDI range of C2 (note 36) to C7 (note 96) is 60, so the PWM compare value required for a linear CV voltage output is basically (note-36)*4.

In terms of timer control registers, this all translates over to (refer to the ATtiny85 data sheet):

  • Set PWM1A i.e. PWM based on OCR1A
  • Set COM1A1 i.e. Clear OC1A (PB1) output line
  • Set CS10 i.e. Prescaler = PCK/CK i.e. run at Clock speed
  • Clear PWM1B is not enabled (GTCCR = 0)

The value for the PWM cycle is set in OCR1C to 239, and the compare value is set in OCR1A between 0 and 239, thus representing a range of 0 to 5v giving 1v per octave, assuming a 5v power supply.

When porting to the ATtiny2313, a similar scheme was used, but timer 1 is a 16 bit timer, and the control registers were slightly different, but I still used the 0-239 range.

Reading around the different modes, I ended opting for the use of Fast PWM with the compare value in OCR1A and the maximum PWM cycle value (239) in ICR1.  The timer register settings were thus as follows:

Timer 1 Control Register A (TCCR1A):

  • 7 COM1A1 = 1 COM1A1(1); COM1A0(0) = Clear OC1A on compare match; set at TOP
  • 6 COM1A0 = 0
  • 5 COM1B1 = 0
  • 4 COM1B0 = 0
  • 3 Resv = 0
  • 2 Resv = 0
  • 1 WGM11 = 1 WGM11(1); WGM10(0) = PWM from OCR1A based on TOP=ICR1
  • 0 WGM10 = 0

Timer 1 Control register B (TCCR1B):

  • 7 ICNC1 = 0
  • 6 ICES1 = 0
  • 5 Resv = 0
  • 4 WGM13 = 1 WGM13(1); WGM12(1) = PWM from OCR1A based on TOP=ICR1
  • 3 WGM12 = 1
  • 2 CS12 = 0 CS12(0); CS11(0); CS10(1) = Prescaler = PCK/CK i.e. run at Clock speed
  • 1 CS11 = 0
  • 0 CS10 = 1

Timer 1 Control Register C left all zeros.

I don’t know if it was the version of the ATtinyCore I was using, but the bit and register definitions for Timer1 for the ATtiny2313 didn’t seem to match the datasheet, so I just used the bit codes directly.

In terms of ATtiny2313 pin definitions, the following were used:

  • Hardware serial receive on D0 (PD0) which is physical pin 2.
  • Gate output on D11 (PB2) which is physical pin 14.
  • CV output using the PWM signal tied to OC1A triggered off timer 1, which is D12 (PB3) on physical pin 15.

A quick note on the MIDI serial handling.  My first code was very lazy and basically said:

Loop:  IF (serial data received) THEN    read MIDI command value    IF (MIDI note on received) THEN      read MIDI note value      read MIDI velocity value      set CV out value based on MIDI note value      set Gate signal HIGH    ELSE IF (MIDI note off received) THEN      read MIDI note value      read MIDI velocity value      set CV out value based on MIDI note value      set Gate signal LOW    ELSE      ignore and go round again waiting for serial data    ENDIF  ENDIFEND Loop

This generated a very quirky set of issues.  Basically when there was serial data available and a MIDI note on or off command detected, the read of the note and velocity data was returning and error (-1) which I never bothered checking.  Basically the code was running too fast and the next MIDI byte hadn’t registered yet.  So when (-1) was passed on as the MIDI note, it was resulting in a note on code thinking the MIDI note was 255, which was rounded up to the highest note (96).

The result was that I could see the gate pulsing in response to MIDI note on and off messages, but the CV voltage went high as soon as the first MIDI message was received.

The next version used a test that said

IF (at least three bytes of serial data received) THEN

which means that if things get out of sync, eventually bytes are skipped until there are three bytes that equate to a note on/off message.  Crude, but it worked enough to show the principle.

The final code includes proper handling of the “Running Status” of MIDI, as described here: http://midi.teragonaudio.com/tech/midispec/run.htm

November 2020 Update:

I’ve moved the channel handling into the command checking – the code was getting confused in a multi-channel data stream as the channel handling was performed too early and not reset properly.

June 2021 Update:

I’ve fixed a couple of issues with the Note Off handling.  Essentially it wasn’t checking that the Note Off event corresponded to the currently playing note, so if you had overlapping notes, the CV would change, but the Note Off from the first note playing would then stop the second note playing too.

July 2021 Update:

Added a TRIGGER output on pin 5.  Note that this is really at my limit of being able to test, so consider it experimental, but please do let me know how you get on and be sure to report back if there are any issues!

There are now four functions that determine how the GATE and TRIGGER work – gateOn, gateOff, triggerOn, triggerOff.  By default these use HIGH for “on” and LOW for “off” but that is now easily changed in these functions if you need (for example) a negative TRIGGER or somesuch.  They are both 5V signals largely straight out of the ATtiny85’s IO pins.

The width of the TRIGGER pulse itself is set at the top of the file to 1000 micro-seconds (i.e. 1 millisecond).  You can change this to whatever you like, but I’m not sure what would happen if you try to go much shorted than a mS, but see how you go.  Ultimately it is limited by the time it takes the ATtiny85 to run the loop() and the resolution of the micros() function.

I used the 8MHz internal clock for the ATtiny85 so be sure to “set the fuses” (i.e. use the “program bootloader” option) to this effect.

To test all of it together, I used my ATtiny85 MIDI Tester.

I might add some kind of selection for the MIDI channel.  Right now its hard-coded in a #define.  One option might be using an analogue input and a multi-position switch with a resistor network.  Or maybe a “tap to increase the channel” digital input switch.  Or if I use the 2313 version, I could use more pins and use a BCD or hex rotary switch or DIP switches.

Here is the full code for the ATtiny85 version, which can be loaded up from the Arduino environment using the ATtiny85 core by Spence Konde. 

// MIDI to CV using ATTiny85// NB: Use Sparkfun USB ATTiny85 Programmer// Set Arduino env to USBTinyISP (Slow)// Set to 8MHz Internal Clock (required for MIDI baud)//// Update: Nov 2020 - fixed channel handling// Update: Jun 2021 - fixed NoteOff/gate handling// Update: Jul 2021 - added trigger output//#include <SoftwareSerial.h>//#define CVOUTTEST 1//#define MIDITEST 1#define MIDIRX 3 // 3=PB3/D3 in Arduino terms = Pin 2 for ATTiny85#define MIDITX 4 // 4=PB4/D4 in Arduino terms = Pin 3 for ATTiny85#define MIDICH 1 // Set this to the MIDI channel to listen to (1 to 16)#define MIDILONOTE 36#define MIDIHINOTE 96// Output:// PB2 (Ardiuno D2) = Pin 7 = Gate Output// PB1 (Arduino D1) = Pin 6 = Pitch CV Output// PB0 (Arduino D0) = Pin 5 = Trigger Output//// PB1 used as PWM output for Timer 1 compare OC1A#define GATE 2 // PB2 (Pin 7) Gate#define PITCHCV 1 // PB1 (Pin 6) Pitch CV#define TRIGGER 0 // PB0 (Pin 5) Trigger#define TRIGPULSE 1000 // Width of the trigger pulse (uS)SoftwareSerial midiSerial(MIDIRX, MIDITX);byte noteplaying;uint32_t pulsemicros;void setup() {  // put your setup code here, to run once:  midiSerial.begin (31250); // MIDI Baud rate  pinMode (GATE, OUTPUT);  pinMode (PITCHCV, OUTPUT);  pinMode (TRIGGER, OUTPUT);  // Use Timer 1 for PWM output based on Compare Register A  // However, set max compare value to 239 in Compare Register C  // This means that output continually swings between 0 and 239  // MIDI note ranges accepted are as follows:  // Lowest note = 36 (C2)  // Highest note = 96 (C7)  // So there are 60 notes that can be received, thus making each  // PWM compare value 240/60 i.e. steps of 4.  //  // So, for each note received, PWM Compare value = (note-36)*4.  //  // Timer 1 Control Register:  // PWM1A = PWM based on OCR1A  // COM1A1 = Clear OC1A (PB1) output line  // CS10 = Prescaler = PCK/CK i.e. run at Clock speed  // PWM1B is not enabled (GTCCR = 0)  //  TCCR1 = _BV(PWM1A)|_BV(COM1A1)|_BV(CS10);  GTCCR = 0;  OCR1C = 239;  OCR1A = 0; // Initial Pitch CV = 0 (equivalent to note C2)  gateOff();  triggerOff();}void setTimerPWM (uint16_t value) {  OCR1A = value;}void gateOn() {  digitalWrite (GATE, HIGH);}void gateOff() {  digitalWrite (GATE, LOW); }void triggerOn() {  digitalWrite (TRIGGER, HIGH);  pulsemicros = micros() + TRIGPULSE;}void triggerOff() {  // Turn off the trigger only after a short delay  if (pulsemicros < micros()) {    digitalWrite (TRIGGER, LOW);  }}void loop() {#ifdef CVOUTTEST  for (midi_note=36; midi_note<=90; midi_note++) {    midiNoteOn (midi_note, 64);    delay (500);    midiNoteOff (midi_note, 0);    delay (500);  }#else  if (midiSerial.available()) {    // pass any data off to the MIDI handler a byte at a time    doMIDI (midiSerial.read());  }#endif  triggerOff();}uint8_t MIDIRunningStatus=0;uint8_t MIDINote=0;uint8_t MIDILevel=0;void doMIDI (uint8_t midibyte) {  // MIDI supports the idea of Running Status.  // If the command is the same as the previous one,   // then the status (command) byte doesn't need to be sent again.  //  // The basis for handling this can be found here:  // http://midi.teragonaudio.com/tech/midispec/run.htm  //  // copied below:  // Buffer is cleared (ie, set to 0) at power up.  // Buffer stores the status when a Voice Category Status (ie, 0x80 to 0xEF) is received.  // Buffer is cleared when a System Common Category Status (ie, 0xF0 to 0xF7) is received.  // Nothing is done to the buffer when a RealTime Category message is received.  // Any data bytes are ignored when the buffer is 0.  //  if ((midibyte >= 0x80) && (midibyte <= 0xEF)) {    //    // MIDI Voice category message    //    // Start handling the RunningStatus    MIDIRunningStatus = midibyte;    MIDINote = 0;    MIDILevel = 0;  }  else if ((midibyte >= 0xF0) && (midibyte <= 0xF7)) {    //    // MIDI System Common Category message    //    // Reset RunningStatus    MIDIRunningStatus = 0;  }  else if ((midibyte >= 0xF8) && (midibyte <= 0xFF)) {    //    // System real-time message    //    // Ignore these and no effect on the RunningStatus  } else {    //    // MIDI Data    //    if (MIDIRunningStatus == 0) {      // No record of state, so not something we can      // process right now, so ignore until we've picked      // up a command to process      return;    }    // Note: Looking for the command on our channel    if (MIDIRunningStatus == (0x80|(MIDICH-1))) {      // First find the note      if (MIDINote == 0) {        MIDINote = midibyte;      } else {        // If we already have a note, assume its the level        MIDILevel = midibyte;        // Now we have a note/velocity pair, act on it        midiNoteOff (MIDINote, MIDILevel);        MIDINote = 0;        MIDILevel = 0;      }    } else if (MIDIRunningStatus == (0x90|(MIDICH-1))) {      if (MIDINote == 0) {        MIDINote = midibyte;      } else {        // If we already have a note, assume its the level        MIDILevel = midibyte;        // Now we have a note/velocity pair, act on it        if (MIDILevel == 0) {          midiNoteOff (MIDINote, MIDILevel);        } else {          midiNoteOn (MIDINote, MIDILevel);        }        MIDINote = 0;        MIDILevel = 0;      }    } else {      // MIDI command we don't process or not on our channel    }  }}void midiNoteOn (byte midi_note, byte midi_level) {  // check note in the correct range of 36 (C2) to 90 (C7)  if (midi_note < MIDILONOTE) midi_note = MIDILONOTE;  if (midi_note > MIDIHINOTE) midi_note = MIDIHINOTE;  // Scale to range 0 to 239, with 1 note = 4 steps  midi_note = midi_note - MIDILONOTE;  // Set the voltage of the Pitch CV and Enable the Gate and Trigger  setTimerPWM(midi_note*4);  gateOn();  triggerOn();  noteplaying = midi_note;#ifdef MIDITEST  // Write back ASCII (binary)  midiSerial.print (midi_note+36, HEX);#endif}void midiNoteOff (byte midi_note, byte midi_level) {  // check note in the correct range of 36 (C2) to 90 (C7)  if (midi_note < MIDILONOTE) midi_note = MIDILONOTE;  if (midi_note > MIDIHINOTE) midi_note = MIDIHINOTE;  // Scale to range 0 to 239, with 1 note = 4 steps  midi_note = midi_note - MIDILONOTE;  // Only trigger the gate/OFF if it corresponds to the currnent note sounding  if (midi_note == noteplaying) {    noteplaying = 0;    // Set the voltage of the Pitch CV and Disable the Gate    gateOff();    // Your choice: Do you want to:    // Clear the CV down to zero on NoteOff?    // Set the CV to the same note as the NoteOff?    // Completely leave it as it was (probably the same note as the NoteOff)?//    setTimerPWM(0); // Clear to zero//    setTimerPWM(midi_note*4); // Set to midi_note  }#ifdef MIDITEST  midiSerial.print (0xAA, HEX);#endif}

#attiny2313 #attiny85 #define #else #endif #ifdef #include #midi #midi2cv

MIDItoCV3_schem2019-03-02 16.00.27
2025-11-28

@adventure
#If VBA7 Then
' 64bit / 新しいExcel用
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
#Else
' 32bit Excel用
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

もうちょっと続くんじゃよ

Top10KoreaTop10KOREA
2025-11-22

Today's New Kpop (1122)

SATURDAY PREACHER - CHA EUN-WOO (차은우)

youtu.be/jdP8ZXSflqg?si=CpTPXt


Client Info

Server: https://mastodon.social
Version: 2025.07
Repository: https://github.com/cyevgeniy/lmst