From 78863f98c01d6f5834c18d2fc12ffd391837ba47 Mon Sep 17 00:00:00 2001 From: San Jacobs Date: Fri, 6 Jun 2025 19:46:10 +0200 Subject: Sound Devices support is back! (Tested with 688) --- README.md | 6 +- build.bat | 4 +- main.odin | 167 +++++++++++++++++++++++++++++++++++++++++++++++------- parts/start2.html | 2 +- 4 files changed, 155 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 2f8d8a7..4115c5e 100755 --- a/README.md +++ b/README.md @@ -4,9 +4,11 @@ Makes your sound reports better. Turns the awkward CSVs into a beautiful self-contained HTML file. -Latest version only works with reports from Zoom F8-series at the moment (Tested with F8n Pro). -Sound Devices support will be coming back soon, but if you need it NOW, use commit `f93340dd`. +## Tested on reports from: + +- Sound Devices 688 +- Zoom F8n Pro ## Enbettermentifications diff --git a/build.bat b/build.bat index 4fcbc93..b413d1b 100755 --- a/build.bat +++ b/build.bat @@ -1,2 +1,2 @@ -odin build . -debug -pdb-name:bin/better-report.pdb -out:bin/better-report.exe -odin run . -o:speed -out:C:/tools/better-report.exe -- test/ \ No newline at end of file +odin run . -debug -pdb-name:bin/better-report.pdb -out:bin/better-report.exe -- test +odin build . -o:speed -out:C:/tools/better-report.exe \ No newline at end of file diff --git a/main.odin b/main.odin index 139bfb5..b7978f1 100755 --- a/main.odin +++ b/main.odin @@ -7,7 +7,8 @@ import "core:sys/windows" import "core:strings" /* -TODO: Support Sound Devices CSVs again +TODO: Drag-n-drop window +TODO: Testing with 8-series */ VERBOSE :: false @@ -19,7 +20,7 @@ PART_END :: #load("parts/end.html", string) Device :: enum { UNSET, ZOOM, - SOUND_DEVICES, + SD6, } Stages :: enum { @@ -62,16 +63,17 @@ main :: proc() { path_info, error := os.stat(input_file_name) + file_count := 1 + files_done := 0 if error == os.ERROR_NONE { file_list : [dynamic]string - file_count := 1 if(path_info.is_dir) { fmt.println("Directory submitted! Walking directory...\n") fmt.printf("📁 {}\n", path_info.name) walk_directory(path_info.fullpath, &file_count, &file_list, 1) - fmt.println("") } else { + fmt.println("File submitted! Processing file...\n") append(&file_list, strings.clone(path_info.fullpath)) } @@ -84,13 +86,16 @@ main :: proc() { fmt.printf("Parse failed: {}\n", file_info.fullpath) continue } - output_name := fmt.aprintf("{}_Knekt.html", file_info.fullpath[:len(file_info.fullpath)-4], allocator=context.temp_allocator) + output_name := fmt.aprintf("{}/{}_Lydrapport.html", filepath.dir(file_info.fullpath), parsed.title, allocator=context.temp_allocator) render(parsed, output_name) free_all(context.temp_allocator) + files_done += 1 } } else { fmt.printf("ERROR could not get path info for: {}\n", input_file_name) } + + fmt.printf("\nCompleted {}/{} files.\n\n", files_done, file_count-1) } @@ -107,12 +112,12 @@ parse :: proc(path : string, device : Device = .UNSET) -> (Report, bool) { file_info, _ := os.lstat(path, context.temp_allocator) + lines := strings.split_lines(string(data), allocator=context.temp_allocator) + // STAGE 1 -------------------------------------------------------------- // First, we detect what kind of sound report this is - line_number := 0 - it := string(data) - for line in strings.split_lines_iterator(&it) { + for line, line_number in lines { if (device!=.UNSET) { break } if line == "\"SOUND REPORT\"," { device = .ZOOM @@ -123,10 +128,9 @@ parse :: proc(path : string, device : Device = .UNSET) -> (Report, bool) { if VERBOSE do fmt.printf("Detected ZOOM from \"ZOOM F8\" on line index {}\n", line_number) } if line == "SOUND REPORT" { - device = .SOUND_DEVICES + device = .SD6 if VERBOSE do fmt.printf("Detected SOUND_DEVICES from unquoted SOUND REPORT line index {}\n", line_number) } - line_number += 1 } if device == .UNSET { @@ -151,6 +155,39 @@ parse :: proc(path : string, device : Device = .UNSET) -> (Report, bool) { for &row in output.table { row = make([]string, output.column_count, context.temp_allocator) } + } else if device == .SD6 { + second_to_last_line := lines[len(lines)-2] + output.column_count = strings.count(second_to_last_line, ",") + count_stage : Stages = .TITLE + for line, l in lines { + switch count_stage { + case .TITLE: + if l == 1 { // Ugly magic number, could be fucked by firmware update + count_stage = .INFO + } + case .INFO: + if line == "," { + count_stage = .HEADER + continue + } else if len(line) > 2 { + output.info_line_count += 1 + } + case .HEADER: + if line == "" { + count_stage = .BODY + } + case .BODY: + if len(line)>2 { + output.row_count += 1 + } + } + } + output.info_lines = make([]Info_Line, output.info_line_count+output.column_count, context.temp_allocator) + output.header = make([]string, output.column_count, context.temp_allocator) + output.table = make([][]string, output.row_count, context.temp_allocator) + for &row in output.table { + row = make([]string, output.column_count, context.temp_allocator) + } } @@ -165,12 +202,105 @@ parse :: proc(path : string, device : Device = .UNSET) -> (Report, bool) { stage : Stages = .TITLE #partial switch device { - case .SOUND_DEVICES: - fmt.printf("ERROR parsing {}: Sound Devices reports are not yet supported in this version.\n", path) - return {}, false + case .SD6: + // .d8888b. 8888888b. .d8888b. + // d88P Y88b 888 "Y88b d88P Y88b + // Y88b. 888 888 888 + // "Y888b. 888 888 888d888b. + // "Y88b. 888 888 888P "Y88b + // "888 888 888 888 888 + // Y88b d88P 888 .d88P Y88b d88P + // "Y8888P" 8888888P" "Y8888P" + fmt.printf("Parsing [{}] as Sound Devices 6XX report, ", file_info.name) + if file_info.name[len(file_info.name)-11:len(file_info.name)-3] == "_Report." { + output.title = file_info.name[:len(file_info.name)-11] + } else { + output.title = file_info.name + } + fmt.printf("titled \"{}\".\n", output.title) + + info_line_index := 0 + body_line_index := 0 + for line, line_index in lines { + switch stage { + case .TITLE: + if line_index == 1 { // Ugly magic number, could be fucked by firmware update + stage = .INFO + } + + case .INFO: + if line == "," { + stage = .HEADER + continue + } + line_elements := strings.split(line, ",") + if VERBOSE do fmt.printf(".INFO {}: {}\n", line_index, line_elements) + field := line_elements[0] + entry_raw := line_elements[1] + entry := line_elements[1][1:len(entry_raw)-1] + output.info_lines[info_line_index].field = field + output.info_lines[info_line_index].entry = entry + info_line_index += 1 + + + case .HEADER: + if line == "," { + // This is here because there are a bunch of lines that are just commas before the header + } else if len(line)>3 { + if VERBOSE do fmt.printf(".HEADER {}:", line_index) + // No trailing comma in the header?? + for element, e in strings.split(line, ",") { + if VERBOSE do fmt.printf(" {}", element) + + output.header[e] = element + if element[:4] == "Trk " { + if first_channel_index == -1 do first_channel_index = e + last_channel_index = e + } + if element == "Start TC" { + output.tc_column_index = e + } + } + + if VERBOSE do fmt.printf("\n") + } else if line == "" { + stage = .BODY + if VERBOSE do fmt.printf("first_channel_index: {}\n", first_channel_index) + if VERBOSE do fmt.printf("last_channel_index: {}\n", last_channel_index) + } + + + case .BODY: + if len(line) > 2 { + if VERBOSE do fmt.printf(".BODY {}:", line_index) + // to skip empty entry after trailing comma we do a silly slice + for element, e in strings.split(line, ",")[:output.column_count] { + if VERBOSE do fmt.printf(" {}", element) + entry : string = element + // Stripping quotes if after tracks begin + if e >= first_channel_index && (len(element)>0) { + entry = element[1:len(element)-1] + } + output.table[body_line_index][e] = entry + } + if VERBOSE do fmt.printf("\n") + body_line_index += 1 + } + + + } + } case .ZOOM: + // 8888888888 .d8888b. + // 888 d88P Y88b + // 888 Y88b. d88P + // 8888888 "Y88888" + // 888 .d8P""Y8b. + // 888 888 888 + // 888 Y88b d88P + // 888 "Y8888P" fmt.printf("Parsing [{}] as ZOOM report, ", file_info.name) // Getting title @@ -180,14 +310,14 @@ parse :: proc(path : string, device : Device = .UNSET) -> (Report, bool) { output.title = file_info.name[4:len(file_info.name)-4] } else if file_info.name[:3] == "F8_" { // TODO: Verify this is what the original F8 does output.title = file_info.name[4:len(file_info.name)-4] + } else { + output.title = file_info.name } fmt.printf("titled \"{}\".\n", output.title) - line_index := 0 info_line_index := 0 body_line_index := 0 - it := string(data) - for line in strings.split_lines_iterator(&it) { + for line, line_index in lines { switch stage { case .TITLE: if line_index == 1 { // Ugly magic number, could be fucked by firmware update @@ -227,10 +357,10 @@ parse :: proc(path : string, device : Device = .UNSET) -> (Report, bool) { } if VERBOSE do fmt.printf("\n") stage = .BODY - - case .BODY: if VERBOSE do fmt.printf("first_channel_index: {}\n", first_channel_index) if VERBOSE do fmt.printf("last_channel_index: {}\n", last_channel_index) + + case .BODY: if line == "" do break if VERBOSE do fmt.printf(".BODY {}:", line_index) // to skip empty entry after trailing comma we do a silly slice @@ -241,7 +371,6 @@ parse :: proc(path : string, device : Device = .UNSET) -> (Report, bool) { if VERBOSE do fmt.printf("\n") body_line_index += 1 } - line_index += 1 } } diff --git a/parts/start2.html b/parts/start2.html index a357cb7..d7de36f 100755 --- a/parts/start2.html +++ b/parts/start2.html @@ -98,6 +98,6 @@

Lydrapport

-
Version 0.8
+
Version 0.9
-- cgit v1.2.1