吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1200|回复: 12
收起左侧

[C&C++ 原创] 写了一个音频信号路由模拟器,帮助搭建自己的效果链路

[复制链接]
sorrypapa 发表于 2026-4-13 23:09
本帖最后由 sorrypapa 于 2026-4-14 09:31 编辑

结合Ai一起写的模拟器,目前只做了吉他效果器的部分,有需要的小伙伴可以拿源码更新自己想要的效果
经过测试可以正常使用,使用教程在软件左下角非常简单。附上源码+exe文件(解压即可)
--------------------------
这里解释一下用途:为专业录音师、混音师、现场调音师,乐手使用的一个小工具,帮忙搭建效果链路,舞台布线,理清思路。本身不能发声的哦,可以理解为可快速绘制信号路由图示的工具。稍后会更新更多的录音棚,现场扩声模块,供大家使用。
[C++] 纯文本查看 复制代码
#include <graphics.h>
#include <vector>
#include <string>
#include <cmath>
#include <conio.h>
#include <windows.h>

using namespace std;

// ===================== 尺寸 =====================
const int TOOLBAR_WIDTH = 160;
const int WINDOW_WIDTH = 1000;
const int WINDOW_HEIGHT = 700;
const int BLOCK_WIDTH = 42;
const int BLOCK_HEIGHT = 72;
const int PORT_RADIUS = 5;

// 效果器类型
enum EffectType {
    COMPRESSOR, EQ, DISTORTION, REVERB, DELAY,
    GATE, OVERDRIVE, FUZZ, NOISE_GATE, DI
};

string getEffectName(EffectType type) {
    switch (type) {
    case COMPRESSOR: return "压缩";
    case EQ: return "均衡";
    case DISTORTION: return "失真";
    case REVERB: return "混响";
    case DELAY: return "延迟";
    case GATE: return "门限";
    case OVERDRIVE: return "过载";
    case FUZZ: return "法兹";
    case NOISE_GATE: return "清音";
    case DI: return "降噪";
    default: return "效果器";
    }
}

COLORREF getEffectColor(EffectType type) {
    switch (type) {
    case COMPRESSOR: return RGB(40, 160, 255);
    case EQ: return RGB(255, 120, 40);
    case DISTORTION: return RGB(255, 60, 60);
    case REVERB: return RGB(60, 255, 100);
    case DELAY: return RGB(200, 60, 255);
    case GATE: return RGB(50, 200, 200);
    case OVERDRIVE: return RGB(255, 140, 0);
    case FUZZ: return RGB(180, 0, 0);
    case NOISE_GATE: return RGB(80, 80, 220);
    case DI: return RGB(120, 120, 120);
    default: return RGB(150, 150, 150);
    }
}

// ===================== 效果器模块 =====================
struct EffectBlock {
    EffectType type;
    int x, y;

    EffectBlock(EffectType t, int x_, int y_) : type(t), x(x_), y(y_) {}

    // 统一扁平风格(左右完全一样)
    void drawWithoutPorts() const {
        setfillcolor(getEffectColor(type));
        solidrectangle(x, y, x + BLOCK_WIDTH, y + BLOCK_HEIGHT);

        settextcolor(WHITE);
        setbkmode(TRANSPARENT);
        settextstyle(16, 0, "微软雅黑"); // 统一小字体
        outtextxy(x + 6, y + 26, getEffectName(type).c_str());

        setfillcolor(BLACK);
        solidcircle(x + 9, y + 12, 5);
        solidcircle(x + 21, y + 12, 5);
        solidcircle(x + 33, y + 12, 5);
        
        setlinestyle(PS_SOLID, 1);
        setlinecolor(BLACK);
        line(x+5,y+25,x+37,y+25);
                
        setfillcolor(WHITE);
        solidcircle(x + 21, y + 60, 5);
        
    }

    // 统一扁平风格 + 端口
    void drawWithPorts() const {
        setfillcolor(getEffectColor(type));
        solidrectangle(x, y, x + BLOCK_WIDTH, y + BLOCK_HEIGHT);

        settextcolor(WHITE);
        setbkmode(TRANSPARENT);
        settextstyle(16, 0, "微软雅黑"); // 统一小字体,不超出
        outtextxy(x + 6, y + 26, getEffectName(type).c_str());

        setfillcolor(BLACK);
        solidcircle(x + 9, y + 12, 5);
        solidcircle(x + 21, y + 12, 5);
        solidcircle(x + 33, y + 12, 5);
        
        setlinestyle(PS_SOLID, 1);
        setlinecolor(BLACK);
        line(x+5,y+25,x+37,y+25);

        setfillcolor(WHITE);
        solidcircle(x + 21, y + 60, 5);

        setfillcolor(WHITE);
        solidcircle(getInPortX(), getInPortY(), PORT_RADIUS);
        setfillcolor(YELLOW);
        solidcircle(getOutPortX(), getOutPortY(), PORT_RADIUS);
    }

    int getInPortX() const { return x; }
    int getInPortY() const { return y + BLOCK_HEIGHT / 2; }
    int getOutPortX() const { return x + BLOCK_WIDTH; }
    int getOutPortY() const { return y + BLOCK_HEIGHT / 2; }

    bool isPointIn(int mx, int my) const {
        return mx >= x && mx <= x + BLOCK_WIDTH && my >= y && my <= y + BLOCK_HEIGHT;
    }
    bool isClickInPort(int mx, int my) const {
        return hypot(mx - getInPortX(), my - getInPortY()) <= PORT_RADIUS + 4;
    }
    bool isClickOutPort(int mx, int my) const {
        return hypot(mx - getOutPortX(), my - getOutPortY()) <= PORT_RADIUS + 4;
    }
};

// ===================== 连线结构 =====================
struct Connection {
    bool fromMainInput = false;
    int fromBlock = -1;

    bool toMainOutput = false;
    int toBlock = -1;
};

// ===================== 全局变量 =====================
vector<EffectBlock> blocks;
vector<Connection> connections;

// 左侧工具栏:两列布局
vector<EffectBlock> toolbarBlocks = {
    EffectBlock(COMPRESSOR, 20, 50),
    EffectBlock(EQ,         20, 140),
    EffectBlock(DISTORTION, 20, 230),
    EffectBlock(REVERB,     20, 320),
    EffectBlock(DELAY,      20, 410),
    EffectBlock(GATE,       90, 50),
    EffectBlock(OVERDRIVE,  90, 140),
    EffectBlock(FUZZ,       90, 230),
    EffectBlock(NOISE_GATE, 90, 320),
    EffectBlock(DI,         90, 410),
};

bool draggingBlock = false;
int dragIndex = -1;
bool drawingLine = false;
int lineFromIndex = -1;
int lineStartX, lineStartY;
bool lineFromInput = false;
bool needRedraw = true;

const int MAIN_IN_X = TOOLBAR_WIDTH + 40;
const int MAIN_IN_Y = 40;
const int MAIN_OUT_X = WINDOW_WIDTH - 40;
const int MAIN_OUT_Y = WINDOW_HEIGHT - 40;

// ===================== 函数声明 =====================
void drawAll();
void onMouse();
void drawMainIO();

// ===================== 主函数 =====================
int main() {
    initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);
    BeginBatchDraw();

    DWORD lastFrame = GetTickCount();
    const int FPS = 60;
    const int frameDelay = 1000 / FPS;

    while (true) {
        onMouse();

        DWORD now = GetTickCount();
        if (now - lastFrame >= frameDelay) {
            if (needRedraw) {
                drawAll();
                needRedraw = false;
            }
            lastFrame = now;
        }
        Sleep(1);
    }

    closegraph();
    return 0;
}

void drawMainIO() {
    // 总输入(扁平)
    setfillcolor(RGB(220, 60, 60));
    solidrectangle(MAIN_IN_X - 35, MAIN_IN_Y - 22, MAIN_IN_X + 35, MAIN_IN_Y + 22);
    settextcolor(WHITE);
    settextstyle(22, 0, "微软雅黑");
    outtextxy(MAIN_IN_X - 20, MAIN_IN_Y - 12, "IN");
    setfillcolor(YELLOW);
    solidcircle(MAIN_IN_X + 35, MAIN_IN_Y, 7);

    // 总输出(扁平)
    setfillcolor(RGB(60, 200, 80));
    solidrectangle(MAIN_OUT_X - 35, MAIN_OUT_Y - 22, MAIN_OUT_X + 35, MAIN_OUT_Y + 22);
    settextcolor(WHITE);
    settextstyle(22, 0, "微软雅黑");
    outtextxy(MAIN_OUT_X - 22, MAIN_OUT_Y - 12, "OUT");
    setfillcolor(WHITE);
    solidcircle(MAIN_OUT_X - 35, MAIN_OUT_Y, 7);
}

void drawAll() {
    cleardevice();

    // 工具栏背景
    setfillcolor(RGB(40, 40, 40));
    solidrectangle(0, 0, TOOLBAR_WIDTH, WINDOW_HEIGHT);
    settextcolor(WHITE);
    settextstyle(24, 0, "微软雅黑");
    outtextxy(25, 12, "效果器栏");

    settextstyle(16, 0, "微软雅黑");
    outtextxy(12, 600, "白色 = 输入端口");
    outtextxy(12, 625, "黄色 = 输出端口");
    outtextxy(12, 650, "输出→输入 连线");
    outtextxy(12, 675, "右键删除模块");

    for (auto& b : toolbarBlocks)
        b.drawWithoutPorts();

    // 画布
    setfillcolor(RGB(30, 30, 50));
    solidrectangle(TOOLBAR_WIDTH, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    drawMainIO();

    // 连线
    setlinecolor(YELLOW);
    setlinestyle(PS_SOLID, 2);
    for (const auto& conn : connections) {
        if (conn.fromMainInput && conn.toBlock >= 0 && conn.toBlock < (int)blocks.size()) {
            const auto& t = blocks[conn.toBlock];
            line(MAIN_IN_X + 35, MAIN_IN_Y, t.getInPortX(), t.getInPortY());
        } else if (conn.toMainOutput && conn.fromBlock >= 0 && conn.fromBlock < (int)blocks.size()) {
            const auto& f = blocks[conn.fromBlock];
            line(f.getOutPortX(), f.getOutPortY(), MAIN_OUT_X - 35, MAIN_OUT_Y);
        } else if (conn.fromBlock >= 0 && conn.toBlock >= 0 &&
            conn.fromBlock < (int)blocks.size() && conn.toBlock < (int)blocks.size()) {
            const auto& f = blocks[conn.fromBlock];
            const auto& t = blocks[conn.toBlock];
            line(f.getOutPortX(), f.getOutPortY(), t.getInPortX(), t.getInPortY());
        }
    }

    // 效果器
    for (auto& b : blocks)
        b.drawWithPorts();

    // 临时连线
    if (drawingLine) {
        POINT p;
        GetCursorPos(&p);
        ScreenToClient(GetHWnd(), &p);
        setlinecolor(YELLOW);
        setlinestyle(PS_DASH, 2);
        line(lineStartX, lineStartY, p.x, p.y);
        setlinestyle(PS_SOLID, 1);
    }

    FlushBatchDraw();
}

void onMouse() {
    if (!MouseHit()) return;

    MOUSEMSG m = GetMouseMsg();
    needRedraw = true;

    if (m.uMsg == WM_LBUTTONDOWN) {
        if (hypot(m.x - (MAIN_IN_X + 35), m.y - MAIN_IN_Y) < 10) {
            drawingLine = true;
            lineFromInput = true;
            lineStartX = MAIN_IN_X + 35;
            lineStartY = MAIN_IN_Y;
            return;
        }
        for (int i = 0; i < (int)blocks.size(); i++) {
            if (blocks[i].isClickOutPort(m.x, m.y)) {
                drawingLine = true;
                lineFromInput = false;
                lineFromIndex = i;
                lineStartX = blocks[i].getOutPortX();
                lineStartY = blocks[i].getOutPortY();
                return;
            }
        }
        for (int i = 0; i < (int)toolbarBlocks.size(); i++) {
            if (toolbarBlocks[i].isPointIn(m.x, m.y)) {
                blocks.emplace_back(toolbarBlocks[i].type, m.x - BLOCK_WIDTH / 2, m.y - BLOCK_HEIGHT / 2);
                dragIndex = (int)blocks.size() - 1;
                draggingBlock = true;
                return;
            }
        }
        for (int i = 0; i < (int)blocks.size(); i++) {
            if (blocks[i].isPointIn(m.x, m.y)) {
                dragIndex = i;
                draggingBlock = true;
                return;
            }
        }
    }

    if (m.uMsg == WM_LBUTTONUP) {
        if (drawingLine) {
            bool connected = false;
            for (int i = 0; i < (int)blocks.size(); i++) {
                if (blocks[i].isClickInPort(m.x, m.y)) {
                    Connection c;
                    if (lineFromInput)
                        c.fromMainInput = true;
                    else
                        c.fromBlock = lineFromIndex;
                    c.toBlock = i;
                    connections.push_back(c);
                    connected = true;
                    break;
                }
            }
            if (!connected && !lineFromInput) {
                if (hypot(m.x - (MAIN_OUT_X - 35), m.y - MAIN_OUT_Y) < 10) {
                    Connection c;
                    c.fromBlock = lineFromIndex;
                    c.toMainOutput = true;
                    connections.push_back(c);
                }
            }
            drawingLine = false;
        }
        draggingBlock = false;
        dragIndex = -1;
    }

    if (m.uMsg == WM_MOUSEMOVE && draggingBlock && dragIndex != -1) {
        if (m.x > TOOLBAR_WIDTH) {
            blocks[dragIndex].x = m.x - BLOCK_WIDTH / 2;
            blocks[dragIndex].y = m.y - BLOCK_HEIGHT / 2;
        }
    }

    if (m.uMsg == WM_RBUTTONDOWN) {
        for (int i = 0; i < (int)blocks.size(); i++) {
            if (blocks[i].isPointIn(m.x, m.y)) {
                blocks.erase(blocks.begin() + i);
                vector<Connection> temp;
                for (const auto& c : connections) {
                    if (c.fromBlock == i || c.toBlock == i) continue;
                    Connection nc = c;
                    if (nc.fromBlock > i) nc.fromBlock--;
                    if (nc.toBlock > i) nc.toBlock--;
                    temp.push_back(nc);
                }
                connections.swap(temp);
                break;
            }
        }
    }

    if (kbhit()) {
        if (getch() == 32) {
            blocks.clear();
            connections.clear();
            needRedraw = true;
        }
    }
}
批注 2026-04-13 231059.png

SignalRouteSimulator.zip

425.54 KB, 下载次数: 12, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 2吾爱币 +8 热心值 +2 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
kdzhz + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| sorrypapa 发表于 2026-4-14 09:23
zakang 发表于 2026-4-14 04:50
干嘛的?能改变听歌的音质?

不是的哦,模拟信号路由的。很多吉他手或者音乐人有自己的效果器连接链路,复杂的情况下会有很多不同的跳线,在不同设备之间发送返回,可以帮忙理清楚思路的一个小工具
wyxnyj 发表于 2026-4-14 06:37
zakang 发表于 2026-4-14 04:50
干嘛的?能改变听歌的音质?

应该是可以模拟吉他,弹奏歌曲。挺棒的&#128077;
zakang 发表于 2026-4-14 04:50
skzhaixing 发表于 2026-4-14 06:55
下了  这是干什么用的  连了也不能播放 也没有任何声音 动画 演示  就单纯的拖色块连线么
风子09 发表于 2026-4-14 07:12
下一站QSC
小鸟会飞 发表于 2026-4-14 07:39
作曲用的吗
Manson9527 发表于 2026-4-14 07:54
用途呢?
gonga 发表于 2026-4-14 08:09
界面不够现代化啊,大老再美化下
douyacai 发表于 2026-4-14 08:32
那要调整音质模式,是手动拖动,连线吗
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-15 01:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表