Coder Social home page Coder Social logo

purpl3f0x / mqa_identifier Goto Github PK

View Code? Open in Web Editor NEW
115.0 11.0 9.0 118 KB

Master Quality Authenticated codec reverse engineering, Tool to identify MQA encoding and Master's Sample Rate

License: Apache License 2.0

CMake 6.29% C++ 89.28% QMake 4.42%
cplusplus flac mqa cplusplus-17 reverse-engineering audio-codec libflac meridian lossless lossless-music

mqa_identifier's Introduction

MQA Identifier

Small tool to identify MQA encoding in .flac files.

Download latest release here

Gui tool availlable on releases

Usage

./MQA_identifier {name_of_file.flac} or {name_of_folder_to_scan} ++

For example ./MQA_identifier "C:\Music\Mike Oldfield - Tubular Bells\(01) [Mike Oldfield] Part One.flac" "C:\Music\Queen - News Of The World"


More detailed instructions here here



This project isn't related nor endorsed with MQA Ltd. and is made for purely educational purposes)



Stavros Avramidis Never Settle & Keep Running

mqa_identifier's People

Contributors

besha1 avatar ktcar214 avatar purpl3f0x avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mqa_identifier's Issues

Force file scan in alphabetical order

Is it possible to force scanning the files in alphabetical order?
Or at least printing the output in alphabetical order?

Right now I get something like this:

**************************************************
***********  MQA flac identifier tool  ***********
********  Stavros Avramidis (@purpl3F0x)  ********
** https://github.com/purpl3F0x/MQA_identifier  **
**************************************************
Found 9 file for scanning...

  #	Encoding	Name
  1	MQA 44.1K 	06 - Bellyache [MQA 24_44].flac
  2	MQA 44.1K 	01 - COPYCAT [MQA 24_44].flac
  3	MQA 44.1K 	02 - Idontwannabeyouanymore [MQA 24_44].flac
  4	MQA 44.1K 	04 - Watch [MQA 24_44].flac
  5	MQA 44.1K 	09 - &Burn (feat. Vince Staples) [MQA 24_44].flac
  6	MQA 44.1K 	03 - My Boy [MQA 24_44].flac
  7	MQA 44.1K 	05 - Party Favor [MQA 24_44].flac
  8	MQA 44.1K 	07 - Ocean Eyes [MQA 24_44].flac
  9	MQA 44.1K 	08 - Hostage [MQA 24_44].flac

**************************************************
Scanned 9 files
Found 9 MQA files

Since I'm saving the logs, it would be nice the have the first track scanned first, second - second and so forth.

Include Folder in output

I'd like to scan a complete folder with a lot of artist and album subfolders, containing the audiofiles.
Is there already an option, to include the every folder when the folder to scan contains subfolder?
Perfect would be once, when changing to the next subfolder or alternatively for every scanned autiod file.

By the way, great tool you developed here!

Problem with the definition of MQA in some files

I ran into a problem that MQA_identifier does not define all MQA files as MQA
I compared the work of MQA_identifier with the work of is_mqa.py this guy here
https://github.com/redsudo/mqaid
So MQA_identifier does not find many MQA files where is_mqa.py find

I looked at your implementation and the implementation is_mqa.py.They are similar and I found the problem as it seems to me.

The problem is that you check once if (buffer == 0xbe0498c88)
found in buffer |= ((static_cast<uint32_t>(s[0]) ^ static_cast<uint32_t>(s[1])) >> pos) & 1u;
from the value const auto pos = (this->decoder.bps - 16u);

In is_mqa.py the check takes place in the range from 16 to 24
samples = list(iter_data(sound_data))
streams = (Bits((x ^ y) >> p & 1
for x, y in zip(samples[::2], samples[1::2]))
for p in range(16, 24))

My tests showed that need to check at least three times
Need to check with at least three values from pos

something like this

uint64_t buffer = 0;
uint64_t buffer1 = 0;
uint64_t buffer2 = 0;

const auto pos = (this->decoder.bps - 16u); // aim for 16th bit

for (const auto &s: this->decoder.samples) {
buffer |= ((static_cast<uint32_t>(s[0]) ^ static_cast<uint32_t>(s[1])) >> pos) & 1u;
buffer1 |= ((static_cast<uint32_t>(s[0]) ^ static_cast<uint32_t>(s[1])) >> pos +1) & 1u;
buffer2 |= ((static_cast<uint32_t>(s[0]) ^ static_cast<uint32_t>(s[1])) >> pos+2) & 1u;

 if (buffer == 0xbe0498c88) {
    this->isMQA_ = true;
    // Get Original Sample Rate
    // Get MQA Studio
    // We are done return true
    return true;
 } else
 if (buffer1 == 0xbe0498c88) {
    this->isMQA_ = true;
    // Get Original Sample Rate
    // Get MQA Studio
    // We are done return true
    return true;
 } else
 if (buffer2 == 0xbe0498c88) {
    this->isMQA_ = true;
    // Get Original Sample Rate
    // Get MQA Studio
    // We are done return true
     return true;
 } else
 buffer = (buffer << 1u) & 0xFFFFFFFFFu;
 buffer1 = (buffer1 << 1u) & 0xFFFFFFFFFu;
 buffer2 = (buffer2 << 1u) & 0xFFFFFFFFFu;

}
return false;

With such changes, MQA_identifier works perfectly,

If you are interested, I also added in the MQA_identifier
If MQA is found, Vorbis tags are added to the flac file
ENCODER = MQAEncode v1.1, 2.3.3+800 (a505918)
MQAENCODER = MQAEncode v1.1, 2.3.3+800 (a505918)
ORIGINALSAMPLERATE = value from MQA_identifier id.originalSampleRate()

Issue with identifying DSD source

Current identification of DSD source isn't not correct.
Eudora REcords records in native DSD.

Eudora MQA 352.9KHz (from DSD 256 ???)
001110000000001100001000000000100101000000010100011010000000000001000000001000011110001111111001010100100011100011

Normal MQA 352.9KHz
001110000000001100001000000000100101000000010100011010000000000001000000001000011110001111111100110100100011100011

Seems there is a difference on bit 93-97.

Linux building problem

dell@dell-Vostro-14-3468:~/Downloads/mqa$ cmake ../MQA_identifier-1.3/gui/
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dell/Downloads/mqa
dell@dell-Vostro-14-3468:~/Downloads/mqa$ make
Scanning dependencies of target MQA_identifier_gui_autogen
[ 20%] Automatic MOC and UIC for target MQA_identifier_gui
[ 20%] Built target MQA_identifier_gui_autogen
Scanning dependencies of target MQA_identifier_gui
[ 40%] Building CXX object CMakeFiles/MQA_identifier_gui.dir/MQA_identifier_gui_autogen/mocs_compilation.cpp.o
cc1plus: error: /home/dell/Downloads/MQA_identifier-1.3/gui/CMakeLists.txt/../mainwindow.h: Not a directory
make[2]: *** [CMakeFiles/MQA_identifier_gui.dir/build.make:63: CMakeFiles/MQA_identifier_gui.dir/MQA_identifier_gui_autogen/mocs_compilation.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:77: CMakeFiles/MQA_identifier_gui.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
dell@dell-Vostro-14-3468:~/Downloads/mqa$```

"MQB" - Preserve MQA bits for DSP

Possible, that this code is enough for preserving MQA signaling on a first unfolded stream and doing DSP on it.
Something Like:

MQA Decoder -> MQBSlice -> DSP -> Copy -> ... -> DAC as MQA renderer
                  >------------------^
namespace MQBUtils {

unsigned* Alloc(unsigned n) {
  return  (unsigned*)new unsigned[(n + 31) / 32];
}

unsigned* MQBSlice(unsigned* mqb, int off, int count) {
  unsigned* numArray = MQBAlloc(count);
  for (auto i = 0u; i < count; i++) {
    int num = (off + i) / 32;
    int num1 = (off + i) % 32;
    int num2 = i / 32;
    int num3 = i % 32;

    if (((unsigned long)mqb[num] & (unsigned long)(1 << (num1 & 31))) == 0) {
      numArray[num2] &= ~(1 << (num3 & 31));
    } else {
      numArray[num2] = numArray[num2] | 1 << (num3 & 31);
    }
  }

  return numArray;
}

void Copy(unsigned* src, int src_off, unsigned* dst, int dst_off, int count,
          int dst_size) {
  unsigned num;
  for (int i = 0; i < count; i++) {
    int srcOff = (src_off + i) / 32;
    int srcOff1 = (src_off + i) % 32;
    int dstOff = (dst_off + i) / 32;
    int dstOff1 = (dst_off + i) % 32;

    if (srcOff < (int)dst_size) {
      num = src[srcOff];
    } else {
      num = 0;
    }

    if (((unsigned long)num & (long)(1 << (srcOff1 & 31))) == 0) {
      dst[dstOff] &= ~(1 << (dstOff1 & 31));
    } else {
      dst[dstOff] = dst[dstOff] | 1 << (dstOff1 & 31);
    }
  }
}

}  // namespace MQBUtils

Won't build even with libogg installed

:~/tmp/MQA_identifier-1.3$ make
[ 50%] Linking CXX executable MQA_identifier
/usr/bin/ld: cannot find -lOGG
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/MQA_identifier.dir/build.make:84: MQA_identifier] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/MQA_identifier.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Stuck on file

Nice program.
I run this on my collection and it got stuck on a file name:
(03) [Jocelyn B. Smith (01)] It's Alright (01).flac

Maybe it's something related to the file content?

RE libmqadevices

There is a library called libmqadevices that is used for various software (roon, tidal app...), to identify the DACs' mqa state (rendering, full decoding) and others sort of stuff. It's dynamically linked (.dylib) on osx and statically hidden somewhere in Windows.
It should seems to be easy to I implement and the calls are just HID reports.
Side-quest TO-DO in the future.๐Ÿ˜๐Ÿ™‚

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.