@@ -8463,58 +8463,83 @@ uint16_t mode_2DAkemi(void) {
84638463 const uint16_t cols = SEGMENT.virtualWidth();
84648464 const uint16_t rows = SEGMENT.virtualHeight();
84658465
8466- if (SEGENV.call == 0) {SEGMENT.fill(BLACK);}
8466+ if (SEGENV.call == 0) { SEGMENT.fill(BLACK); }
84678467
8468- uint16_t counter = (strip.now * ((SEGMENT.speed >> 2) +2)) & 0xFFFF;
8469- counter = counter >> 8;
8468+ // --- Pre-calculate values before the loops ---
8469+ uint16_t counter = (strip.now * ((SEGMENT.speed >> 2) + 2)) >> 8;
8470+
8471+ // Pre-calculate all color variations ONCE
8472+ const CRGB baseFaceColor = SEGMENT.color_wheel(counter);
8473+ const CRGB baseArmsColor = SEGCOLOR(1) > 0 ? SEGCOLOR(1) : 0xFFE0A0;
8474+ const CRGB eyesMouthColor = SEGCOLOR(2) > 0 ? SEGCOLOR(2) : 0xFFFFFF;
8475+
8476+ // Use faster integer scaling instead of floats
8477+ const uint8_t lightFactorInt = 40; // 0.15 * 255
8478+ const uint8_t normalFactorInt = 102; // 0.4 * 255
8479+
8480+ CRGB lightFaceColor = baseFaceColor; lightFaceColor.nscale8_video(lightFactorInt);
8481+ CRGB normalFaceColor = baseFaceColor; normalFaceColor.nscale8_video(normalFactorInt);
84708482
8471- const float lightFactor = 0.15f ;
8472- const float normalFactor = 0.4f ;
8483+ CRGB lightArmsColor = baseArmsColor; lightArmsColor.nscale8_video(lightFactorInt) ;
8484+ CRGB normalArmsColor = baseArmsColor; normalArmsColor.nscale8_video(normalFactorInt) ;
84738485
8486+ // Cache audio data
84748487 um_data_t *um_data = getAudioData();
84758488 uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
8476- if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
8477- float base = fftResult[0]/255.0f;
8478-
8479- //draw and color Akemi
8480- for (int y=0; y < rows; y++) for (int x=0; x < cols; x++) {
8481- CRGB color;
8482- CRGB soundColor = ORANGE;
8483- CRGB faceColor = SEGMENT.color_wheel(counter);
8484- CRGB armsAndLegsColor = SEGCOLOR(1) > 0 ? SEGCOLOR(1) : 0xFFE0A0; //default warmish white 0xABA8FF; //0xFF52e5;//
8485- uint8_t ak = pgm_read_byte_near(akemi + ((y * 32)/rows) * 32 + (x * 32)/cols); // akemi[(y * 32)/rows][(x * 32)/cols]
8486- switch (ak) {
8487- case 3: armsAndLegsColor.r *= lightFactor; armsAndLegsColor.g *= lightFactor; armsAndLegsColor.b *= lightFactor; color = armsAndLegsColor; break; //light arms and legs 0x9B9B9B
8488- case 2: armsAndLegsColor.r *= normalFactor; armsAndLegsColor.g *= normalFactor; armsAndLegsColor.b *= normalFactor; color = armsAndLegsColor; break; //normal arms and legs 0x888888
8489- case 1: color = armsAndLegsColor; break; //dark arms and legs 0x686868
8490- case 6: faceColor.r *= lightFactor; faceColor.g *= lightFactor; faceColor.b *= lightFactor; color=faceColor; break; //light face 0x31AAFF
8491- case 5: faceColor.r *= normalFactor; faceColor.g *= normalFactor; faceColor.b *= normalFactor; color=faceColor; break; //normal face 0x0094FF
8492- case 4: color = faceColor; break; //dark face 0x007DC6
8493- case 7: color = SEGCOLOR(2) > 0 ? SEGCOLOR(2) : 0xFFFFFF; break; //eyes and mouth default white
8494- case 8: if (base > 0.4) {soundColor.r *= base; soundColor.g *= base; soundColor.b *= base; color=soundColor;} else color = armsAndLegsColor; break;
8495- default: color = BLACK; break;
8496- }
8497-
8498- if (SEGMENT.intensity > 128 && um_data && fftResult[0] > 128) { //dance if base is high
8499- SEGMENT.setPixelColorXY(x, 0, BLACK);
8500- SEGMENT.setPixelColorXY(x, y+1, color);
8501- } else
8502- SEGMENT.setPixelColorXY(x, y, color);
8489+ if (um_data && um_data->u_data) {
8490+ memcpy(fftResult, um_data->u_data[2], sizeof(fftResult));
8491+ }
8492+ const uint8_t fftBase = fftResult[0];
8493+ const bool isDancing = (SEGMENT.intensity > 128 && fftBase > 128);
8494+
8495+ // --- Main drawing loop ---
8496+ for (int y = 0; y < rows; y++) {
8497+ // Pre-calculate the row offset for the akemi bitmap to avoid division in the x-loop
8498+ uint16_t y_offset = ((y * 32) / rows) * 32;
8499+
8500+ for (int x = 0; x < cols; x++) {
8501+ CRGB color = BLACK; // Default to BLACK
8502+ uint8_t ak = pgm_read_byte_near(akemi + y_offset + (x * 32) / cols);
8503+
8504+ switch (ak) {
8505+ case 1: color = baseArmsColor; break;
8506+ case 2: color = normalArmsColor; break;
8507+ case 3: color = lightArmsColor; break;
8508+ case 4: color = baseFaceColor; break;
8509+ case 5: color = normalFaceColor; break;
8510+ case 6: color = lightFaceColor; break;
8511+ case 7: color = eyesMouthColor; break;
8512+ case 8:
8513+ if (fftBase > 102) { // 0.4 * 255
8514+ color = CRGB(ORANGE).nscale8_video(fftBase);
8515+ } else {
8516+ color = baseArmsColor;
8517+ }
8518+ break;
8519+ }
8520+
8521+ if (isDancing) {
8522+ SEGMENT.setPixelColorXY(x, y + 1, color);
8523+ if (y==0) SEGMENT.setPixelColorXY(x, 0, BLACK); // Clear top row only once
8524+ } else {
8525+ SEGMENT.setPixelColorXY(x, y, color);
8526+ }
8527+ }
85038528 }
85048529
8505- //add geq left and right
8530+ // --- GEQ drawing loop (largely unchanged, but with cached um_data) ---
85068531 if (um_data) {
8507- int xMax = cols/ 8;
8508- for (int x= 0; x < xMax; x++) {
8509- size_t band = map2(x, 0, max(xMax,4), 0, 15); // map 0..cols/8 to 16 GEQ bands
8532+ int xMax = cols / 8;
8533+ for (int x = 0; x < xMax; x++) {
8534+ size_t band = map2(x, 0, max(xMax, 4), 0, 15);
85108535 uint32_t color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0);
85118536 band = constrain(band, 0, 15);
8512- uint16_t barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32);
8537+ uint16_t barHeight = map(fftResult[band], 0, 255, 0, 17 * rows / 32);
8538+ barHeight = constrain(barHeight, 0, (rows / 2) + 1);
85138539
8514- barHeight = constrain(barHeight, 0, (rows/2)+1); // map() may overshoot
8515- for (int y=0; y < barHeight; y++) {
8516- SEGMENT.setPixelColorXY(x, rows/2-y, color);
8517- SEGMENT.setPixelColorXY(cols-1-x, rows/2-y, color);
8540+ for (int y = 0; y < barHeight; y++) {
8541+ SEGMENT.setPixelColorXY(x, rows / 2 - y, color);
8542+ SEGMENT.setPixelColorXY(cols - 1 - x, rows / 2 - y, color);
85188543 }
85198544 }
85208545 }
0 commit comments