BinWave Early access
Native desktop workbench for data files

BinWave

See inside any file.

Open binary captures, CSV logs, or any file as bytes. Describe the format in YAML or Python, then plot, inspect, and edit the data, even in multi-gigabyte files.

  • Native desktop app
  • YAML or Python decoders
  • CSV, binary, or any file
  • Byte editing with undo / redo
Try the live demo on real bytes ↓
Early access

Get BinWave on your own data.

Opens a pre-filled email to hello@buildincharge.com

waveform_demo_2gb.bin2.0 GB · 31,249,935 samples
BinWave workspace with one selection linked across four views: the plot cursor at sample 100, the decoded samples row 100 with sine = -1.530734 at byte offset 0x2900, eight highlighted hex bytes labeled sine · f64, and the Inspector showing -1.5307337294603587 1 2 3 4
PlotCursor on sample 100. Twelve channels, samples 64–191 of 31,249,935.
Decoded samplesRow 100, sine cell = -1.530734, byte offset 0x2900.
HexExactly 8 bytes, 0x2900–0x2907, labeled sine · f64.
InspectorFull value -1.5307337294603587, ready to edit or export.
Real capture of the app, not a mockup. Bytes 61 A9 AE A6 E2 7D F8 BF read as a little-endian f64 reproduce the Inspector value exactly.
Try it · real bytes

One selection. Every view connected.

Below are the first 384 samples of the demo capture, 24,576 bytes loaded straight from waveform_demo_2gb.bin and decoded in your browser with the same 64-byte layout. Hover or tap the plot, or use the arrow keys, and watch the table row, hex bytes, and value follow.

Data samples · 31249935 samples Loading bytes…
Plot hover · click to pin · ←→ sample · ↑↓ channel
Inspector
sine
Sample 100
-1.5307337294603587
Path
samples[100].sine
Type
f64 · Little endian
Field bytes
0x2900..0x2908 (end exclusive)
Hex one 64-byte sample record
Cursor 0x2907 · 0x2900-0x2907 · 8 selected bytes sine·f64
Decoded samples click a value to select that field
Want the raw bytes? pwav-samples-0-383.bin is those 24,576 bytes, copied from offset 0x1000 of the demo file.
Decoders

Describe the format. Pick the language that fits it.

Both produce the same plot, table, and cross-probe, and neither one is a fallback for the other. Each keeps its own draft, and switching languages doesn't convert or run your code. F5 runs whichever is active.

waveform.yamlabridged
endian: little
structures:
  Descriptor:
    fields:
      - {name: name, type: text, length: 16}
      - {name: format, type: u32}
      - {name: byte_width, type: u32}

  Descriptions:
    fields:
      - name: entries
        type: Descriptor
        repeat: {ref: /header.descriptor_count}
    actions:
      - define:              # build a type from the file
          name: Sample
          from: entries
          fields:
            name: {ref: name}
            type:
              ref: format
              cases: {'1': u64, '3': f64, '4': f32, '6': i32}
            length: {ref: byte_width}

  Section:
    fields:
      - {name: id, type: u32}
      - {name: payload_bytes, type: u64}
      - name: payload
        type:
          choose:
            ref: id
            cases: {'1': Descriptions, '2': Samples, '3': Footer}
            otherwise: bytes
        length: {ref: payload_bytes}

YAML: a declarative reader

  • Structures describe fields and nested elements, and actions read them, skip or align bytes, calculate values, and choose interpretations.
  • References like /header.descriptor_count use earlier decoded values for counts, lengths, and offsets.
  • define builds a new record type from descriptions found in the file, and choose picks a type by tag.
  • Integers, floats, text, raw byte regions, and calculated values built from what you have already decoded.

No schema yet? Start by selecting bytes.

The YAML editor has Source, Fields, and Steps tabs, and all three edit the same draft. You can build a decoder with forms instead of writing YAML by hand.

01 · Hex

Select the bytes

Drag across a header in Hex and choose Describe selected bytes…, or New from selection in Fields.

02 · Fields

Name and type them

Each field shows its size, position, and live value as you pick a format. A usage meter tracks how much of the selection is described.

03 · Decode

Decode the selection

Decode selection opens the results right away. When the range holds whole records, Decode all N records in this selection appears.

04 · Build on it

Use what you decoded

Use this value for… turns a decoded number into a count, length, or offset. Build a type from these descriptions… turns a table of names into a struct.

Steps forms: Read data · Skip bytes · Align position · Calculate a value · Build type from descriptions · Choose by value

Self-describing files

The decoder reads the layout out of the file.

Neither waveform decoder hardcodes a channel name or a sample offset. The file declares its own columns: twelve descriptors, each a name, a format code, and a byte width. The decoder turns them into a 64-byte Sample type, then walks length-prefixed sections by ID.

headerPWAV v1 · 2,000,000,000 bytes · 4 sections · 12 descriptors
↓ descriptor_count = 12
descriptors12 × 24 bytes: sine f64, triangle f64bit_pattern u32
↓ define Sample from entries
Sample4 × f64 · 4 × f32 · 2 × i32 · 2 × u32 = 64 bytes
↓ repeat until the section ends
samples31,249,935 items · 64 bytes each · starts at 0x1000

Reverse the descriptor order, widen the unknown section, and move the payload from byte 4,096 to 8,192. The same script and the same YAML still decode it.

Decoded structure tree: header (32 bytes) with signature PWAV, version 1, file_bytes 2000000000, sample_count 31249935, section_count 4, descriptor_count 12; descriptors (288 bytes) expanded to show sine and triangle, format 3, byte_width 8; unknown_section_1 of 3728 bytes; samples: 31249935 items · 64 bytes each; footer 48 bytes

Decoded structure: an expandable tree of everything the decoder read, including the unknown section kept as raw bytes.

The YAML decoder editor with Source, Fields, and Steps tabs showing the waveform.yaml definition

The YAML decoder with its Source, Fields, and Steps tabs. F5 decodes.

BinWave plot with all 12 named channels over samples 0–383 of 31,249,935: bit_pattern, counter_ramp, alternating, zigzag, damped_sine, staircase, pulse, square, chirp, ramp, triangle, and sine, with a cursor at sample 100

Plot: 12 channels, samples 0–383, cursor on sample 100. Toolbar: Overview · Zoom in · Zoom out · Lock Y · Fit Y · Fit selection · Select sample range… · Inspect / edit bytes · Export selected bytes…

Plotting

Zoom from millions of samples to one.

Plot any numeric field across the whole collection, with many channels overlaid at once. Zoomed all the way out, peaks and dips stay visible instead of disappearing between pixels. Zoom in and every individual sample is there.

  • Every point keeps its address. Click a peak at any zoom level and you get that sample's exact bytes.
  • Overview shows the whole collection at a glance. Scan for all peaks reads every sample in the current range when you need to be sure nothing was missed.
  • Drag to pan, wheel to zoom, right-drag to zoom to a range. Wheel over an axis to zoom only that axis. Lock Y holds the scale and Fit Y refits it.
  • Select a sample range, then Inspect / edit bytes or Export selected bytes… to write exactly those interleaved records to a file.
Hex · Inspector · Edits

A hex editor that knows the struct.

Hex scrolls smoothly through the whole file, however large, with no paging controls. Decoded fields tint their own byte ranges, and hovering any byte names the narrowest field that covers it.

  • Jump to 0x100, 256, or a relative +256 / -0x10. Ctrl+G focuses it, and Back / Forward retrace your steps.
  • Find hex pairs or text anywhere in the file, then step through matches with Previous and Next.
  • Overwrite mode takes hex pairs or UTF-8 text. Replace bytes… swaps a same-length range.
  • Copy Python read copies a line like file.read_at(0x2900, 8) for the selection. Name / color range… bookmarks bytes without any YAML.
  • Inspector shows the selection as integers and floats in both byte orders, as text, and the first byte's bits. Fixed-width numbers can be edited in place with Apply value.
Hex editor with Back, Forward, Jump, Find, Selection, View and Overwrite controls. Cursor 0x2907, 0x2900–0x2907, 8 selected bytes labeled sine · f64, highlighted in both hex and text columns

Hex: the selection 0x2900–0x2907 is identified as sine · f64 and highlighted in both the hex and text columns.

Inspector panel: sine, Sample 100, value -1.5307337294603587, Apply value, Show field bytes, Export field…, Sample actions; technical details show the definition covers 2000000000 bytes with 6 reusable types, path samples[100].sine, type f64 little endian, field bytes 0x2900..0x2908

Inspector: value, definition path, type, and exact field bytes, with Apply value, Show field bytes, and Export field…

Editing

Edit bytes with full undo.

Overwrite bytes in Hex or change a value in Inspector. Changed bytes stay marked, Undo / Redo steps through your edits, and the decoded views re-run against the edited bytes. Save edited copy… streams the result to disk, and Extract selection… streams just the bytes you selected.

Large files

Built for captures bigger than your RAM.

Hex, tables, and plots read only the part of the file you're looking at, so a capture opens and responds like a small one.

40GB
Synthetic waveform capture, decoded with the same YAML and Python decoders
31.2M
Samples in the 2 GB demo, all reachable in the plot and table
2.2ms
To the first 8,192 rows of a 20 GiB CSV
~71MiB
Memory used while indexing that entire 20 GiB CSV

Timings vary with hardware and disk cache.

CSV

CSV that links back to bytes.

Open a CSV and the first portion plots right away, with no scan to EOF. Table cells and plotted points select their exact raw bytes, quoted and multiline fields included. Index entire file when you want exact totals, and the index resumes when you reopen.

Any file

Open anything as bytes.

.bin, .png, .zip, or no extension at all. Hex is usable immediately, and a file opens with a Byte preview plot. Example decoders for PNG chunks and RIFF/WAVE containers are included.

Workspace

Dock it how you work.

Drag panel titles to split, stack, or float the Decoder, Plot, Hex, Decoded samples, Decoded structure, and Inspector. Your layout persists. Closing a panel keeps its selection and history, and every open and save dialog remembers its own folder.

Early access

Send me the format you're stuck on.

BinWave is built by a working embedded engineer who got tired of writing the same struct.unpack loop for every project. Email a line or two about your data: the log format, the chip, the protocol, and how big the captures get. Early testers shape what ships next.

Opens a pre-filled email to hello@buildincharge.com

Firmware & embeddedYour own logging format, captured during bring-up and debugged a thousand times.
Robotics & telemetryOvernight logs with dozens of channels, where the anomaly is at sample 18 million.
Test & hardware validationInstrument dumps you need to plot, trace back to raw bytes, patch, and hand off.

Not available yet

  • Compressed or computed data as plotted collections
  • Bitfield and UTF-16 field types
  • Inserting or removing bytes
  • Checksum verification and repair
  • Browser version

Python decoders run with your user permissions. YAML definitions can't run code.