cue2audio

cue2audio
其实应该叫cue2mp3的
想快速转换cue的列表文件为mp3,有很多cd要转mp3,写这东西方便一下,嘛,就这些了
代码有的乱,不必介意
如果想转flac的话,自己改ffmpeg的参数吧,我还没用到所以就不理了

操作方法嘛,双击cue2audio.exe打开后,按提示操作,支持拖放,(不要打开非cue文件,可能导致死机)

cue转换mp3 320Kbps

当然有几个问题
1. cue格式要是 本机编码 的 ,我系统的是简体中文所以 本机编码GB2312,推荐使用notepad++来转换编码;如果出现乱码,大半是你的编码没弄好
2. 对 音频文件 不能是 TAK 格式,因为这个 ffmpeg 不支持TAK格式的解码,你可以自己换一个支持TAK格式的ffmpeg,这样就没问题了
3. 输出文件在 output 文件夹里
4. 转换时,所有文件会一起转换,就是有多少首音乐就会弹出多少个窗口,自己试试便知,不要被一大堆窗口吓死
5. 如果新窗口一闪而过,或者有很多红字,一定会音频编码不支持,或者路径名太长了

音频编码不支持解决办法
TAK的话请使用TAK.exe解压为wav,同时修改cue里面音频路径(直接把.tak替换为.wav就行) 链接:http://cloud.189.cn/t/rMnqEjYfuIni (Tak.exe) 我忘记是从哪来的了
TTA格式好像也不行,使用格式工厂转换成wav格式,修改cue里面音频路径就行了

cue2audio src是源代码,cue2audio是成品
链接:http://cloud.189.cn/t/3IBrInYNzQba (cue2audio)

这个是主要代码

#include <Windows.h>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include "TFILE.h"

using namespace std;

struct TRACK
{
    string title;
    string performer;
    vector<string> begintime;
    string endtime      = "00:00:00";
    string control;
};

struct CUE
{
    string performer;
    string title;
    string file;
    vector<string> comment;
    vector<TRACK> tracklist;
};

struct udiv_t
{
    unsigned int quot;
    unsigned int rem;
};
udiv_t mydiv(unsigned int a, unsigned int b)
{
    udiv_t c;
    c.quot = a / b;
    c.rem = a % b;
    return c;
}

//以空格为关键字分裂字符串
vector<string> DivideStringBySpace(string in)
{
    vector<string> sv;
    sv.reserve(20);
    sv.resize(1);
    bool indoublemark = false;  //是否在双引号内
    for (auto &i : in)
    {
        if ((i == '\x20' || i == '\x09') && !indoublemark)
            sv.push_back(string());
        else if (i == '\x22')
            indoublemark = !indoublemark;
        else
            sv.back() += i;
    }
    for (auto i = sv.begin(); i != sv.end();)
    {
        if (*i == "")
            i = sv.erase(i);
        else
            ++i;
    }
    return sv;
}
//消除指定字符
string  EatAllByChar(string in, char a)
{
    for (auto i = in.begin(); i != in.end();)
    {
        if (*i == a)
            i = in.erase(i);
        else
            ++i;
    }
    return in;
}
void    StringSplit(const string& src, const string& separator, vector<string>& dest)
{
    string str = src;
    string substring;
    string::size_type start = 0, index;

    do
    {
        index = str.find_first_of(separator, start);
        if (index != string::npos)
        {
            substring = str.substr(start, index - start);
            dest.push_back(substring);
            start = str.find_first_not_of(separator, index);
            if (start == string::npos) return;
        }
    } while (index != string::npos);

    //the last token
    substring = str.substr(start);
    dest.push_back(substring);
}
UINT    StringToMillisecond(string strtime)         //字符串时间 分:秒:毫秒 转 毫秒
{
    UINT ms = 0;
    vector<string> sa;
    vector<int> sai;
    StringSplit(strtime, ":", sa);
    if (sa.size() < 3)
    {
        MessageBoxA(0, 0, "时间格式错误,异常", 0);
        DebugBreak();
    }               //如果少于3个,跳出
    for (size_t i = 0; i < 3; ++i)
    {
        UINT t = strtoul(sa[i].c_str(), 0, 10);
        switch (i)
        {
            case 0:
                ms = t * 1000 * 60;
                break;
            case 1:
                ms += t * 1000;
                break;
            case 2:
                ms += t;
                break;
        }
    }
    return ms;
}
string  MillisecondToString(UINT ms_)               //毫秒 转字符串时间 时:分:秒.毫秒
{
    string strtime;
    udiv_t h = mydiv(ms_, 1000 * 60 * 60);
    udiv_t m = mydiv(h.rem, 1000 * 60);
    udiv_t s = mydiv(m.rem, 1000);
    UINT ms = s.rem;
    char str[20];
    _ultoa_s(h.quot, str, sizeof(str), 10);
    strtime += str + string(":");
    _ultoa_s(m.quot, str, sizeof(str), 10);
    strtime += str + string(":");
    _ultoa_s(s.quot, str, sizeof(str), 10);
    strtime += str + string(".");
    _ultoa_s(ms, str, sizeof(str), 10);
    strtime += str;
    return strtime;
}



void main()
{
start_:
    SetConsoleTitleA("cue2audio");
    printf("本程序将cue文件转换为mp3\n");
    printf("转换后文件在output文件夹内\n");
    printf("支持拖拽\n");
    printf("请输入cue文件路径\n");

    CUE cue;
    string str;
    //cin >> str;
    getline(cin, str, '\n');
    cin.clear();

    TFILE tf;
    tf.Open(EatAllByChar(str, '\"'));
    if (!tf.IsOpen())
    {
        printf("打开文件失败,请重试\n\n\n");
        goto start_;
    }
    vector<string> sv;
    while (!tf.IsEOF())
    {
        sv = DivideStringBySpace(tf.ReadLine());
        if (sv.size() < 1)
            continue;
        if (sv[0] == "REM")
        {
            string comment;
            for (size_t i = 0; i < sv.size(); ++i)
            {
                comment += sv[i];
                comment += " ";
            }
            comment.erase(--comment.end(), comment.end());
            cue.comment.push_back(comment);
        }
        else if (sv[0] == "PERFORMER")
        {
            if (sv.size() >= 2)
                cue.performer = EatAllByChar(sv[1], '"');
        }
        else if (sv[0] == "TITLE")
        {
            if (sv.size() >= 2)
                cue.title = EatAllByChar(sv[1], '"');
        }
        else if (sv[0] == "FILE")
        {
            if (sv.size() >= 2)
                cue.file = EatAllByChar(sv[1], '"');
        }
        else if (sv[0] == "TRACK")
        {
            break;
        }
    }
    cue.tracklist.reserve(20);
    goto m2;
    while (!tf.IsEOF())
    {
        sv = DivideStringBySpace(tf.ReadLine());
    m2:
        if (sv.size() < 1)
            continue;
        if (sv[0] == "TRACK")
        {
            cue.tracklist.push_back(TRACK());
        }
        else if (sv[0] == "PERFORMER")
        {
            if (sv.size() >= 2)
                cue.tracklist.back().performer = EatAllByChar(sv[1], '"');
        }
        else if (sv[0] == "TITLE")
        {
            if (sv.size() >= 2)
                cue.tracklist.back().title = EatAllByChar(sv[1], '"');
        }
        else if (sv[0] == "INDEX")
        {
            if (sv.size() >= 3)
                cue.tracklist.back().begintime.push_back(sv[2]);
        }

    }
    //生成结束时间
    for (auto i = ++cue.tracklist.begin(); i != cue.tracklist.end(); ++i)
        (i - 1)->endtime = i->begintime.front();
    cue.tracklist.back().endtime = "00:00:00";

    {
        //这段代码执行的可能性基本为0
        //消去时间为0的
        //为没有名字的文件生成文件名
        for (auto i = cue.tracklist.begin(); i != cue.tracklist.end();)
        {
            if (i->begintime.back() == i->endtime)
            {
                i = cue.tracklist.erase(i);
                continue;
            }
            else
                if (i->title == "")
                    i->title = "_";
            ++i;
        }

    }

    //转换时间格式
    for (auto i = cue.tracklist.begin(); i != cue.tracklist.end(); ++i)
    {
        i->begintime.back() = MillisecondToString(StringToMillisecond(i->begintime.back()));
        i->endtime = MillisecondToString(StringToMillisecond(i->endtime));
    }

    //整理重名文件
    for (auto i = cue.tracklist.begin(); i != cue.tracklist.end(); ++i)
    {
    again:
        for (auto j = cue.tracklist.begin(); j != i; ++j)
        {
            if (i->title == j->title)
            {
                i->title += "_";
                goto again;
            }
        }
    }
    //输出指示
    printf("CUE TITLE:    %s\n", cue.title.c_str());
    printf("CUE PERFORMER:%s\n", cue.performer.c_str());
    for (auto &i : cue.tracklist)
    {
        printf("TRACK:    %s\n", i.title.c_str());
        printf("PERFORMER:%s\n", i.performer.c_str());
    }
    //生成控制命令
    string cdmusicoutdirpath = "output\\" + cue.title + "\\";
    CreateDirectoryA("output", 0);
    CreateDirectoryA(cdmusicoutdirpath.c_str(), 0);
    for (auto &i : cue.tracklist)
    {
        //注意空格,不能漏
        i.control += " -y -i ";
        i.control += "\"" + tf.GetFolderName() + cue.file + "\"";
        i.control += " -id3v2_version 3 -ar 44100 -ac 2 -ab 320k ";
        i.control += " -ss " + i.begintime.back();
        i.control += " -to " + i.endtime;
        i.control += " \"" + cdmusicoutdirpath + i.title + ".mp3\"";
    }
    tf.Close(); //不能放在前面结束
    //转换
    vector<HANDLE> hv;
    for (auto &i : cue.tracklist)
    {
        PROCESS_INFORMATION pi;
        STARTUPINFO sp;
        ZeroMemory(&pi, sizeof(pi));
        ZeroMemory(&sp, sizeof(sp));

        auto h = CreateProcessA("ffmpeg.exe", (char *)i.control.c_str(), 0, 0, 0, CREATE_NEW_CONSOLE, 0, 0, &sp, &pi);
        hv.push_back(pi.hProcess);
    }
    WaitForMultipleObjects(hv.size(), hv.data(), true, INFINITE);
    printf("操作完成, 按下回车键继续下一个文件,或者直接关闭本程序窗口退出\n\n\n");
    getchar();
    goto start_;
    return;
}

void FFmpegRUN(string infile, bool isoverwrite, unsigned int audiosamplingrate, unsigned int audiochannel, string begintime, string endtime, bool isblock)
{
    string control;
    control += isoverwrite ? " -y " : "";
    control += " -i \"" + infile + "\" ";
    control += audiosamplingrate == 0 ? "" : (" -ar " + to_string(audiosamplingrate) + " ");
    control += audiochannel == 0 ? "" : (" -ac " + to_string(audiochannel) + " ");

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值