Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Recent Posts
92
3rd Party Plugins - (fb2k) / Re: foo_vis_vumeter
Last post by oops -
I just don't agree with you.
Cool. Disagreements always welcome. Let's find some common ground. From your description of what is actually in the BIN file, I think you're slightly off the mark, let me try to clarify.

What you're describing is closer to the output of VUEditor in that you imply that the (up to) 1024 frames are stored in that BIN file alongside the background. That's not exactly how it is stored. Let's just take on the background and the needle to keep it simple.

The only full image that is stored in the BIN file is the "background" (I think of it as a combination of the static elements "back" and "glass"). As you allude to, VUEditor stores this image in the BIN with the checkerboard pattern for the transparency and it is equivalent to the "Back.bmp" when using VUEditor to render the frames individually. From what you describe, the point of misunderstanding is that the rest of the frames with the needle are also stored in the same method as the "Back.bmp". They are not.

I just don't understand your hesitation to just accept a same dimensioned PNG that replaces the one inside while rendering.
You are using the transparent frames stored in the BIN for overlaying too, because you don't have the needle, glass and light PNG's.
The BIN file stores each frame (really each distinct frame since many positions are repeated), as a difference or delta versus the base image. In other words, it just contains the location and the new color of the pixels that are different. You can see it in the size of the BIN file (even uncompressed) compared to the ballooning size when you dump out the frames from VUEditor. The smart part of the VUEditor and cleverness of the BIN file format is that it uses this compact scheme to store the data, avoids duplication, and yet one is able to recreate every frame. There is no compositing, I simply paint the background and then just substitute the frame-specific pixels.

I've spent endless hours recreating BIN's (and making AIMP from it).
As you experienced, the AIMP version is a nightmare in relation to the BIN method. With every new distinct element added (or "complications" to use watchmaking terminology), it requires extra rotations, translations, transformations, masking, scaling, compositing, and others in specific and unspecified orders to achieve the desired effect.

The background retrieval is a lot easier now because of BINextractor.
As much as I applaud BoringName's initiative to create BINextractor and open up the creativity of the community, I've personally never needed to use the tool. Most everything it does can be done quicker using the already well-done VUEditor and basic/ubiquitous command-line utilities.

Really? People use VU meters and maybe want to put in another background, that's it. They are not developers, programmers or the like.
That does a disservice to the creative effort that it takes to build a VU Meter, whether BIN, AIMP, LVU or some other method and the potpourri of tools at the disposal in a creator's workshop. Heck, using foobar2000 or finding and using VUEditor/GIMP/Affinity/Photoshop requires a bit more skills than your average computer user. If all you just want to do is put a different background on someone else's work, I've explained how. Similarly, if you want to work around a legacy tool's limitation, I outlined how to create it in a generic, reusable form. Work smarter, not harder.

Since no one will take what I said seriously without results, here is a quick-and-dirty Python script (with only stdlib dependencies) to modify your own BIN file to remove the checkerboarding for the "left channel" (the output BIN is uncompressed):
Code: [Select]
import binascii
import io
import lzma
import math
import subprocess
import sys

def decompress_lzma(compressed_path):
    with lzma.open(compressed_path, 'rb', format=lzma.FORMAT_ALONE) as f:
        file_content = f.read()
    return file_content

class HeaderNotSupported(Exception):
    pass

def unhexlify(bytedata):
    return binascii.unhexlify(bytedata)

def bytes2int(bytedata):
    return int.from_bytes(binascii.unhexlify(bytedata), byteorder=sys.byteorder)

def getint(bytedata):
    return int.from_bytes(bytedata, byteorder=sys.byteorder)

def read_bmp(file_path):
    content = None
    with open(file_path, 'rb') as f:
        content = f.read()
        content = binascii.hexlify(content)

    ID = unhexlify(content[:4]).decode('utf-8')
    SIZE = bytes2int(content[4:12])
    RESERVED = bytes2int(content[12:20])
    OFFSET = bytes2int(content[20:28])
    DIBHEADER = bytes2int(content[28:36])
    if DIBHEADER == 124:
        print('Header Type: BITMAPV5HEADER')
        WIDTH = bytes2int(content[36:44])
        HEIGHT = bytes2int(content[44:52])
        NBITSPERPIXEL = bytes2int(content[56:60])
        RAWIMGSIZE = bytes2int(content[68:76])
        PIXELARRAY = unhexlify(content[284:284 + RAWIMGSIZE])
    else:
        raise HeaderNotSupported('Header not supported')
    return OFFSET, RAWIMGSIZE, WIDTH, HEIGHT, NBITSPERPIXEL, PIXELARRAY

def rotate_top_down(width, height, pixel_data):
    row_size = width * 4
    rotated_data = bytearray()
    for row in range(height):
        start = row * row_size
        end = start + row_size
        rotated_data[0:0] = pixel_data[start:end]
    return rotated_data

def substitute_binary_bits(source_file, dest_file, dest_data, source_offset, dest_offset, width, height, bpp, length):
    try:
        with open(source_file, 'rb') as src:
            src.seek(source_offset)
            pixel_data = src.read(length)

        rotated_data = pixel_data  #rotate_top_down(width, height, pixel_data)

        dest = io.BytesIO(dest_data)
        dest.seek(4)
        dest_offset = 8 + getint(dest.read(2)) * math.floor(bpp / 8)
        dest.seek(7)
        zero = getint(dest.read(1))
        zero = bytearray([0xc0 | zero])  # 0x80 if rotated to top-down, 0xc0 if left bottom-up
        dest.seek(7)
        dest.write(zero)
        dest.seek(dest_offset)
        dest.write(rotated_data)

        with open(dest_file, 'wb') as file:
            file.write(dest.getvalue())

        print('Substitution completed successfully.')
    except Exception as e:
        print(f'An error occurred: {e}')

def main():
    compressed_bin = '7inch_3 X RR transparent.bin'
    source_file = 'test.bmp'
    dest_file = 'test.bin'

    command = ['magick.exe', 'L_0.png', 'test.bmp']
    subprocess.run(command, capture_output=False, text=True)
    source_offset, length, width, height, bpp, pixel_data = read_bmp(source_file)
    uncompressed_data = decompress_lzma(compressed_bin)
    substitute_binary_bits(source_file, dest_file, uncompressed_data, source_offset, 8 + 1024 * 4, width, height, bpp, length)

if __name__ == '__main__':
    main()

Figure 1. Left side replaced with transparent bottom-up bitmap. Right side unmodified. Using DUI.

I don't expect anyone to agree with my approach. However, I think separation of concerns between building the data and displaying the data/creator's intent is the right one. I still don't see a compelling reason to have loose PNG files floating around in the vumeter folder or duplicate existing data in an archive (plus double compression) as there is a "simple-ish" method (admittedly not less work) to create the BIN file with the desired properties. In addition, as I see it, by encouraging fixing these observed issues and limitation as close to the originating source as possible we will benefit the ecosystem more than just a loner creating a one-off patch in the downstream viewer.
93
CD Hardware/Software / Ripping CDs on MacOS in 2025
Last post by Axon -
I find myself wanting to rip CDs on a 2024 Mac Mini, outside the Apple ecosystem. A lost cause, I know. It's running Apple Silicon, but that is seemingly not a huge pain point right now.

I can't get XLD to work. I suspect I am encountering #599 XLD hangs detecting pregap, although IIRC, the hang also occurs when I turn pregap detection off.

The few contemporary discussion threads I can find on this subject all seem to end with “use dBpoweramp”. And I am totally willing to conclude that might be the only decent solution. But I'm skeptical, particularly because of the relative preponderance of free and decent rippers on Windows.

abcde (when installed via macports), preposterously... works, by virtue of cdparanoia working. I was never that pleased with abcde on Linux, but I was unable to find any particularly better solution.

Am I missing any other rippers on MacOS which are actively maintained, free or not?
94
Other Lossy Codecs / Re: TOY, a lossy and experimental "do not use" codec
Last post by Klymins -
problems found...  :-\
(i used ratio 7.7 for toy encoding, somewhat near to 160kbps)
btw, when there aren't problems, toy is comparable to mp3, though encoding is much slower.

The problem of 4 appears to be exclusive to ratio mode (more obvious with higher (worse) ratio values). FYI, TOY is much worse than MP3 at lower bitrates (by its nature) (excluding ratio mode because of this bug, I missed this).

Also, these cutoff points (yes, including MP3's) are too high for most people.