cycdp 0.1.1__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cycdp/py.typed ADDED
File without changes
@@ -0,0 +1,558 @@
1
+ Metadata-Version: 2.2
2
+ Name: cycdp
3
+ Version: 0.1.1
4
+ Summary: Cython bindings for the CDP audio processing library
5
+ Keywords: audio,dsp,signal-processing,spectral,granular,cython,cdp
6
+ Author-Email: Shakeeb Alireza <shakfu@users.noreply.github.com>
7
+ License: LGPL-2.1-or-later
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Operating System :: Microsoft :: Windows
15
+ Classifier: Programming Language :: C
16
+ Classifier: Programming Language :: Cython
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Multimedia :: Sound/Audio
24
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
25
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Sound Synthesis
26
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
27
+ Classifier: Typing :: Typed
28
+ Project-URL: Homepage, https://github.com/shakfu/cycdp
29
+ Project-URL: Repository, https://github.com/shakfu/cycdp
30
+ Project-URL: Issues, https://github.com/shakfu/cycdp/issues
31
+ Project-URL: Changelog, https://github.com/shakfu/cycdp/blob/main/CHANGELOG.md
32
+ Requires-Python: >=3.10
33
+ Description-Content-Type: text/markdown
34
+
35
+ # cycdp
36
+
37
+ Python bindings for the CDP (Composers Desktop Project) audio processing library.
38
+
39
+ ## Overview
40
+
41
+ cycdp provides Python access to CDP's extensive audio processing algorithms. It uses Cython with memoryviews and the buffer protocol for zero-copy interoperability with numpy, `array.array`, and other buffer-compatible objects - **no numpy dependency required**.
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ # Build and install in development mode
47
+ make build
48
+
49
+ # Or with uv directly
50
+ uv sync
51
+ ```
52
+
53
+ ## Quick Start
54
+
55
+ ```python
56
+ import cycdp
57
+
58
+ # Load audio file
59
+ buf = cycdp.read_file("input.wav")
60
+
61
+ # Apply processing
62
+ stretched = cycdp.time_stretch(buf, stretch_factor=2.0)
63
+ shifted = cycdp.pitch_shift(buf, semitones=5)
64
+
65
+ # Save result
66
+ cycdp.write_file("output.wav", stretched)
67
+ ```
68
+
69
+ ## Usage
70
+
71
+ ### High-level API
72
+
73
+ Works with any float32 buffer (numpy arrays, `array.array('f')`, memoryview, etc.):
74
+
75
+ ```python
76
+ import array
77
+ import cycdp
78
+
79
+ # Create sample data
80
+ samples = array.array('f', [0.5, 0.3, -0.2, 0.8, -0.4])
81
+
82
+ # Apply gain (linear or decibels)
83
+ result = cycdp.gain(samples, gain_factor=2.0)
84
+ result = cycdp.gain_db(samples, db=6.0) # +6dB = ~2x
85
+
86
+ # Normalize to target peak level
87
+ result = cycdp.normalize(samples, target=1.0)
88
+ result = cycdp.normalize_db(samples, target_db=-3.0) # -3dBFS
89
+
90
+ # Phase invert
91
+ result = cycdp.phase_invert(samples)
92
+
93
+ # Find peak level
94
+ level, position = cycdp.peak(samples)
95
+ ```
96
+
97
+ ### With numpy
98
+
99
+ ```python
100
+ import numpy as np
101
+ import cycdp
102
+
103
+ samples = np.random.randn(44100).astype(np.float32) * 0.5
104
+ result = cycdp.normalize(samples, target=0.9)
105
+
106
+ # Result supports buffer protocol - zero-copy to numpy
107
+ output = np.asarray(result)
108
+ ```
109
+
110
+ ### File I/O
111
+
112
+ ```python
113
+ import cycdp
114
+
115
+ # Read audio file (returns Buffer)
116
+ buf = cycdp.read_file("input.wav")
117
+
118
+ # Write audio file
119
+ cycdp.write_file("output.wav", buf)
120
+ ```
121
+
122
+ ### Low-level API
123
+
124
+ For more control, use explicit Context and Buffer objects:
125
+
126
+ ```python
127
+ import cycdp
128
+
129
+ # Create context and buffer
130
+ ctx = cycdp.Context()
131
+ buf = cycdp.Buffer.create(1000, channels=2, sample_rate=44100)
132
+
133
+ # Fill buffer
134
+ for i in range(len(buf)):
135
+ buf[i] = 0.5
136
+
137
+ # Process in-place
138
+ cycdp.apply_gain(ctx, buf, 2.0, clip=True)
139
+ cycdp.apply_normalize(ctx, buf, target_level=0.9)
140
+
141
+ # Get peak info
142
+ level, pos = cycdp.get_peak(ctx, buf)
143
+
144
+ # Access via buffer protocol
145
+ mv = memoryview(buf)
146
+ ```
147
+
148
+ ## API Reference
149
+
150
+ ### File I/O
151
+
152
+ | Function | Description |
153
+ |----------|-------------|
154
+ | `read_file(path)` | Read audio file, returns Buffer |
155
+ | `write_file(path, buffer)` | Write buffer to audio file |
156
+
157
+ ### Gain and Normalization
158
+
159
+ | Function | Description |
160
+ |----------|-------------|
161
+ | `gain(samples, gain_factor, ...)` | Apply linear gain |
162
+ | `gain_db(samples, db, ...)` | Apply gain in decibels |
163
+ | `normalize(samples, target, ...)` | Normalize to target peak (0-1) |
164
+ | `normalize_db(samples, target_db, ...)` | Normalize to target dB |
165
+ | `phase_invert(samples, ...)` | Invert phase |
166
+ | `peak(samples, ...)` | Find peak level and position |
167
+
168
+ ### Spatial and Panning
169
+
170
+ | Function | Description |
171
+ |----------|-------------|
172
+ | `pan(samples, position, ...)` | Pan mono to stereo (-1 to 1) |
173
+ | `pan_envelope(samples, envelope, ...)` | Pan with time-varying envelope |
174
+ | `mirror(samples, ...)` | Mirror/swap stereo channels |
175
+ | `narrow(samples, width, ...)` | Adjust stereo width (0=mono, 1=full) |
176
+
177
+ ### Mixing
178
+
179
+ | Function | Description |
180
+ |----------|-------------|
181
+ | `mix(buffers, ...)` | Mix multiple buffers together |
182
+ | `mix2(buf1, buf2, ...)` | Mix two buffers |
183
+
184
+ ### Buffer Utilities
185
+
186
+ | Function | Description |
187
+ |----------|-------------|
188
+ | `reverse(samples, ...)` | Reverse audio |
189
+ | `fade_in(samples, duration, ...)` | Apply fade in |
190
+ | `fade_out(samples, duration, ...)` | Apply fade out |
191
+ | `concat(buffers, ...)` | Concatenate buffers |
192
+
193
+ ### Channel Operations
194
+
195
+ | Function | Description |
196
+ |----------|-------------|
197
+ | `to_mono(samples, ...)` | Convert to mono |
198
+ | `to_stereo(samples, ...)` | Convert mono to stereo |
199
+ | `extract_channel(samples, channel, ...)` | Extract single channel |
200
+ | `merge_channels(left, right, ...)` | Merge two mono buffers to stereo |
201
+ | `split_channels(samples, ...)` | Split stereo to two mono buffers |
202
+ | `interleave(channels, ...)` | Interleave multiple mono buffers |
203
+
204
+ ### Time and Pitch
205
+
206
+ | Function | Description |
207
+ |----------|-------------|
208
+ | `time_stretch(samples, stretch_factor, ...)` | Time stretch without pitch change |
209
+ | `modify_speed(samples, speed, ...)` | Change speed (affects pitch) |
210
+ | `pitch_shift(samples, semitones, ...)` | Shift pitch without time change |
211
+
212
+ ### Spectral Processing
213
+
214
+ | Function | Description |
215
+ |----------|-------------|
216
+ | `spectral_blur(samples, blur_amount, ...)` | Blur/smear spectrum over time |
217
+ | `spectral_shift(samples, shift, ...)` | Shift spectrum up/down |
218
+ | `spectral_stretch(samples, stretch, ...)` | Stretch/compress spectrum |
219
+ | `spectral_focus(samples, freq, bandwidth, ...)` | Focus on frequency region |
220
+ | `spectral_hilite(samples, freq, gain, ...)` | Highlight frequency region |
221
+ | `spectral_fold(samples, freq, ...)` | Fold spectrum around frequency |
222
+ | `spectral_clean(samples, threshold, ...)` | Remove spectral noise |
223
+
224
+ ### Filters
225
+
226
+ | Function | Description |
227
+ |----------|-------------|
228
+ | `filter_lowpass(samples, cutoff, ...)` | Low-pass filter |
229
+ | `filter_highpass(samples, cutoff, ...)` | High-pass filter |
230
+ | `filter_bandpass(samples, low, high, ...)` | Band-pass filter |
231
+ | `filter_notch(samples, freq, width, ...)` | Notch/band-reject filter |
232
+
233
+ ### Dynamics and EQ
234
+
235
+ | Function | Description |
236
+ |----------|-------------|
237
+ | `gate(samples, threshold, ...)` | Noise gate |
238
+ | `compressor(samples, threshold, ratio, ...)` | Dynamic range compressor |
239
+ | `limiter(samples, threshold, ...)` | Peak limiter |
240
+ | `eq_parametric(samples, freq, gain, q, ...)` | Parametric EQ band |
241
+ | `envelope_follow(samples, ...)` | Extract amplitude envelope |
242
+ | `envelope_apply(samples, envelope, ...)` | Apply envelope to audio |
243
+
244
+ ### Effects
245
+
246
+ | Function | Description |
247
+ |----------|-------------|
248
+ | `bitcrush(samples, bits, ...)` | Bit depth reduction |
249
+ | `ring_mod(samples, freq, ...)` | Ring modulation |
250
+ | `delay(samples, time, feedback, ...)` | Delay effect |
251
+ | `chorus(samples, depth, rate, ...)` | Chorus effect |
252
+ | `flanger(samples, depth, rate, ...)` | Flanger effect |
253
+ | `reverb(samples, size, damping, ...)` | Reverb effect |
254
+
255
+ ### Envelope Shaping
256
+
257
+ | Function | Description |
258
+ |----------|-------------|
259
+ | `dovetail(samples, fade_time, ...)` | Apply dovetail fades |
260
+ | `tremolo(samples, rate, depth, ...)` | Tremolo effect |
261
+ | `attack(samples, attack_time, ...)` | Modify attack transient |
262
+
263
+ ### Distortion
264
+
265
+ | Function | Description |
266
+ |----------|-------------|
267
+ | `distort_overload(samples, gain, ...)` | Overload/saturation distortion |
268
+ | `distort_reverse(samples, ...)` | Reverse distortion effect |
269
+ | `distort_fractal(samples, ...)` | Fractal distortion |
270
+ | `distort_shuffle(samples, ...)` | Shuffle distortion |
271
+ | `distort_cut(samples, cycle_count, ...)` | Waveset cut with decaying envelope |
272
+ | `distort_mark(samples, markers, ...)` | Interpolate wavesets at time markers |
273
+ | `distort_repeat(samples, multiplier, ...)` | Time-stretch by repeating wavecycles |
274
+ | `distort_shift(samples, group_size, ...)` | Shift/swap half-wavecycle groups |
275
+ | `distort_warp(samples, warp, ...)` | Progressive warp distortion with sample folding |
276
+
277
+ ### Granular Processing
278
+
279
+ | Function | Description |
280
+ |----------|-------------|
281
+ | `brassage(samples, ...)` | Granular brassage |
282
+ | `freeze(samples, position, ...)` | Granular freeze at position |
283
+ | `grain_cloud(samples, density, ...)` | Granular cloud synthesis |
284
+ | `grain_extend(samples, extension, ...)` | Granular time extension |
285
+ | `texture_simple(samples, ...)` | Simple texture synthesis |
286
+ | `texture_multi(samples, ...)` | Multi-layer texture synthesis |
287
+
288
+ ### Morphing and Cross-synthesis
289
+
290
+ | Function | Description |
291
+ |----------|-------------|
292
+ | `morph(buf1, buf2, amount, ...)` | Spectral morph between sounds |
293
+ | `morph_glide(buf1, buf2, ...)` | Gliding morph over time |
294
+ | `cross_synth(carrier, modulator, ...)` | Cross-synthesis (vocoder-like) |
295
+
296
+ ### Analysis
297
+
298
+ | Function | Description |
299
+ |----------|-------------|
300
+ | `pitch(samples, ...)` | Extract pitch data |
301
+ | `formants(samples, ...)` | Extract formant data |
302
+ | `get_partials(samples, ...)` | Extract partial/harmonic data |
303
+
304
+ ### Experimental/Chaos
305
+
306
+ | Function | Description |
307
+ |----------|-------------|
308
+ | `strange(samples, ...)` | Strange attractor transformation |
309
+ | `brownian(samples, ...)` | Brownian motion transformation |
310
+ | `crystal(samples, ...)` | Crystal growth patterns |
311
+ | `fractal(samples, ...)` | Fractal transformation |
312
+ | `quirk(samples, ...)` | Quirky transformation |
313
+ | `chirikov(samples, ...)` | Chirikov map transformation |
314
+ | `cantor(samples, ...)` | Cantor set transformation |
315
+ | `cascade(samples, ...)` | Cascade transformation |
316
+ | `fracture(samples, ...)` | Fracture transformation |
317
+ | `tesselate(samples, ...)` | Tesselation transformation |
318
+
319
+ ### Playback/Time Manipulation
320
+
321
+ | Function | Description |
322
+ |----------|-------------|
323
+ | `zigzag(samples, times, ...)` | Alternating forward/backward playback through time points |
324
+ | `iterate(samples, repeats, ...)` | Repeat audio with pitch shift and gain decay variations |
325
+ | `stutter(samples, segment_ms, ...)` | Segment-based stuttering with silence inserts |
326
+ | `bounce(samples, bounces, ...)` | Bouncing ball effect with accelerating repeats |
327
+ | `drunk(samples, duration, ...)` | Random "drunk walk" navigation through audio |
328
+ | `loop(samples, start, length_ms, ...)` | Loop a section with crossfades and variations |
329
+ | `retime(samples, ratio, ...)` | Time-domain time stretch/compress (TDOLA) |
330
+ | `scramble(samples, mode, ...)` | Reorder wavesets (shuffle, reverse, by size/level) |
331
+ | `splinter(samples, start, ...)` | Fragmenting effect with shrinking repeats |
332
+ | `hover(samples, frequency, location, ...)` | Zigzag reading at specified frequency for hovering pitch effect |
333
+ | `constrict(samples, constriction)` | Shorten or remove silent sections |
334
+ | `phase_invert(samples)` | Invert phase (multiply all samples by -1) |
335
+ | `phase_stereo(samples, transfer)` | Enhance stereo separation via phase subtraction |
336
+ | `wrappage(samples, grain_size, density, ...)` | Granular texture with stereo spatial distribution |
337
+
338
+ ### Spatial Effects
339
+
340
+ | Function | Description |
341
+ |----------|-------------|
342
+ | `spin(samples, rate, ...)` | Rotate audio around stereo field with optional doppler |
343
+ | `rotor(samples, pitch_rate, amp_rate, ...)` | Dual-rotation modulation (pitch + amplitude interference) |
344
+ | `flutter(samples, frequency, depth, ...)` | Spatial tremolo (loudness modulation alternating L/R) |
345
+
346
+ ### Extended Granular
347
+
348
+ | Function | Description |
349
+ |----------|-------------|
350
+ | `grain_reorder(samples, mode, ...)` | Reorder detected grains (shuffle, reverse, rotate) |
351
+ | `grain_rerhythm(samples, factor, ...)` | Change timing/rhythm of grains |
352
+ | `grain_reverse(samples, ...)` | Reverse individual grains in place |
353
+ | `grain_timewarp(samples, factor, ...)` | Time-stretch/compress grain spacing |
354
+ | `grain_repitch(samples, semitones, ...)` | Pitch-shift grains with interpolation |
355
+ | `grain_position(samples, spread, ...)` | Reposition grains in stereo field |
356
+ | `grain_omit(samples, probability, ...)` | Probabilistically omit grains |
357
+ | `grain_duplicate(samples, count, ...)` | Duplicate grains with variations |
358
+
359
+ ### Pitch-Synchronous Operations (PSOW)
360
+
361
+ | Function | Description |
362
+ |----------|-------------|
363
+ | `psow_stretch(samples, stretch_factor, ...)` | Time-stretch while preserving pitch (PSOLA) |
364
+ | `psow_grab(samples, time, duration, ...)` | Extract pitch-synchronous grains from position |
365
+ | `psow_dupl(samples, repeat_count, ...)` | Duplicate grains for time-stretching |
366
+ | `psow_interp(grain1, grain2, ...)` | Interpolate between two grains |
367
+
368
+ ### FOF Extraction and Synthesis (FOFEX)
369
+
370
+ | Function | Description |
371
+ |----------|-------------|
372
+ | `fofex_extract(samples, time, ...)` | Extract single FOF (pitch-synchronous grain) at time |
373
+ | `fofex_extract_all(samples, ...)` | Extract all FOFs to uniform-length bank |
374
+ | `fofex_synth(fof_bank, duration, frequency, ...)` | Synthesize audio from FOFs at target pitch |
375
+ | `fofex_repitch(samples, pitch_shift, ...)` | Repitch audio with optional formant preservation |
376
+
377
+ ### Synthesis
378
+
379
+ | Function | Description |
380
+ |----------|-------------|
381
+ | `synth_wave(waveform, frequency, ...)` | Generate waveforms (sine, square, saw, ramp, triangle) |
382
+ | `synth_noise(pink, amplitude, ...)` | Generate white or pink noise |
383
+ | `synth_click(tempo, beats_per_bar, ...)` | Generate click/metronome track |
384
+ | `synth_chord(midi_notes, ...)` | Synthesize chord from MIDI note list |
385
+
386
+ ### Utility Functions
387
+
388
+ | Function | Description |
389
+ |----------|-------------|
390
+ | `gain_to_db(gain)` | Convert linear gain to decibels |
391
+ | `db_to_gain(db)` | Convert decibels to linear gain |
392
+ | `version()` | Get library version string |
393
+
394
+ ### Low-level Functions
395
+
396
+ These work with explicit Context and Buffer objects:
397
+
398
+ | Function | Description |
399
+ |----------|-------------|
400
+ | `apply_gain(ctx, buf, gain, clip)` | Apply gain in-place |
401
+ | `apply_gain_db(ctx, buf, db, clip)` | Apply dB gain in-place |
402
+ | `apply_normalize(ctx, buf, target)` | Normalize in-place |
403
+ | `apply_normalize_db(ctx, buf, target_db)` | Normalize to dB in-place |
404
+ | `apply_phase_invert(ctx, buf)` | Invert phase in-place |
405
+ | `get_peak(ctx, buf)` | Get peak level and position |
406
+
407
+ ### Classes
408
+
409
+ - `Context` - Processing context (holds error state)
410
+ - `Buffer` - Audio buffer with buffer protocol support
411
+ - `Buffer.create(frames, channels, sample_rate)` - Create new buffer
412
+ - Supports indexing, len(), and memoryview
413
+
414
+ ### Constants
415
+
416
+ **Processing flags:**
417
+ - `FLAG_NONE` - No processing flags
418
+ - `FLAG_CLIP` - Clip output to [-1.0, 1.0]
419
+
420
+ **Waveform types (for `synth_wave`):**
421
+ - `WAVE_SINE` - Sine wave
422
+ - `WAVE_SQUARE` - Square wave
423
+ - `WAVE_SAW` - Sawtooth wave
424
+ - `WAVE_RAMP` - Ramp (reverse sawtooth) wave
425
+ - `WAVE_TRIANGLE` - Triangle wave
426
+
427
+ **Scramble modes (for `scramble`):**
428
+ - `SCRAMBLE_SHUFFLE` - Random shuffle
429
+ - `SCRAMBLE_REVERSE` - Reverse order
430
+ - `SCRAMBLE_SIZE_UP` - Sort by size (smallest first)
431
+ - `SCRAMBLE_SIZE_DOWN` - Sort by size (largest first)
432
+ - `SCRAMBLE_LEVEL_UP` - Sort by level (quietest first)
433
+ - `SCRAMBLE_LEVEL_DOWN` - Sort by level (loudest first)
434
+
435
+ ### Exceptions
436
+
437
+ - `CDPError` - Raised on processing errors
438
+
439
+ ## Architecture
440
+
441
+ ```
442
+ cycdp/ # Project root
443
+ src/cycdp/ # Python package
444
+ __init__.py # Public exports
445
+ _core.pyx # Cython bindings
446
+ cdp_lib.pxd # Cython declarations
447
+ projects/
448
+ libcdp/ # C library
449
+ include/
450
+ cdp.h # Main public API
451
+ cdp_error.h # Error codes
452
+ cdp_types.h # Type definitions
453
+ cdp_lib/
454
+ cdp_lib.h # Library internal header
455
+ cdp_*.h # Category headers (filters, effects, etc.)
456
+ src/
457
+ context.c # Context management
458
+ buffer.c # Buffer management
459
+ gain.c # Gain/amplitude operations
460
+ io.c # File I/O
461
+ channel.c # Channel operations
462
+ mix.c # Mixing operations
463
+ spatial.c # Spatial/panning
464
+ utils.c # Utilities
465
+ error.c # Error handling
466
+ cpd8/ # CDP8 sources (FFT, includes)
467
+ dev/
468
+ tests/ # Python tests
469
+ CMakeLists.txt # Builds extension
470
+ ```
471
+
472
+ ## Demos
473
+
474
+ The `demos/` directory contains example scripts demonstrating cycdp usage.
475
+
476
+ ### Run All Demos
477
+
478
+ ```bash
479
+ make demos # Run all demos, output WAV files to build/
480
+ make demos-clean # Remove generated WAV files
481
+ ```
482
+
483
+ ### Synthesis Demos (01-07)
484
+
485
+ These generate test sounds programmatically and demonstrate the API:
486
+
487
+ ```bash
488
+ python demos/01_basic_operations.py # Buffers, gain, fades, panning, mixing
489
+ python demos/02_effects_and_processing.py # Delay, reverb, modulation, filters
490
+ python demos/03_spectral_processing.py # Blur, time stretch, pitch shift, freeze
491
+ python demos/04_granular_synthesis.py # Brassage, wrappage, grain ops
492
+ python demos/05_pitch_synchronous.py # PSOW, FOF, hover
493
+ python demos/06_creative_techniques.py # Effect chains, recipes
494
+ python demos/07_morphing.py # Morph, glide, cross-synthesis
495
+ ```
496
+
497
+ ### FX Processing Demos (fx01-fx07)
498
+
499
+ CLI tools for processing real audio files:
500
+
501
+ ```bash
502
+ # Basic usage
503
+ python demos/fx01_time_and_pitch.py input.wav -o output_dir/
504
+
505
+ # All FX demos:
506
+ python demos/fx01_time_and_pitch.py input.wav # Time stretch, pitch shift
507
+ python demos/fx02_spectral_effects.py input.wav # Blur, focus, fold, freeze
508
+ python demos/fx03_granular.py input.wav # Brassage, wrappage, grains
509
+ python demos/fx04_reverb_delay_mod.py input.wav # Reverb, delay, modulation
510
+ python demos/fx05_distortion_dynamics.py input.wav # Distortion, filters, dynamics
511
+ python demos/fx06_psow_fof.py input.wav # PSOW, FOF, hover
512
+ python demos/fx07_creative_chains.py input.wav # Complex effect chains
513
+ ```
514
+
515
+ Each FX demo generates multiple output files showcasing different parameter settings.
516
+
517
+ ## Development
518
+
519
+ ```bash
520
+ # Build
521
+ make build
522
+
523
+ # Run tests
524
+ make test
525
+
526
+ # Lint and format
527
+ make lint
528
+ make format
529
+
530
+ # Type check
531
+ make typecheck
532
+
533
+ # Full QA
534
+ make qa
535
+
536
+ # Build wheel
537
+ make wheel
538
+
539
+ # See all targets
540
+ make help
541
+ ```
542
+
543
+ ## Adding New Operations
544
+
545
+ To add more CDP operations:
546
+
547
+ 1. Add C implementation to `projects/libcdp/cdp_lib/<operation>.c`
548
+ 2. Add function declarations to appropriate header in `projects/libcdp/cdp_lib/`
549
+ 3. Export from `projects/libcdp/cdp_lib/cdp_lib.h`
550
+ 4. Update `CMakeLists.txt` to include new source file
551
+ 5. Add Cython declarations to `src/cycdp/cdp_lib.pxd`
552
+ 6. Add Cython bindings to `src/cycdp/_core.pyx`
553
+ 7. Export from `src/cycdp/__init__.py`
554
+ 8. Add tests to `tests/`
555
+
556
+ ## License
557
+
558
+ LGPL-2.1-or-later (same as CDP)
@@ -0,0 +1,8 @@
1
+ cycdp/__init__.py,sha256=S1qzTUlhfviU462i1V6D6P8RL1QaeRwvZ6CQiQCDBUE,7852
2
+ cycdp/_core.cp313-win_amd64.pyd,sha256=VFdf9-dMmH8lfJMK_Vf0cT7tPbYyqbPRtnOL4dJDDhY,972800
3
+ cycdp/_core.pyi,sha256=0JxePcDWyL7_EPjjP9HeCW0OSgppjwcUcz0-WflGQQg,30561
4
+ cycdp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ cycdp-0.1.1.dist-info/METADATA,sha256=VHn9qqTzbfU5urXN6TIVBORjK01aVKSyuNkbvvYCx30,19661
6
+ cycdp-0.1.1.dist-info/WHEEL,sha256=vkL3wTIkhjZa3RmEXX20hldNp6Q8qtwRjrXW6K5sw_Q,106
7
+ cycdp-0.1.1.dist-info/licenses/LICENSE,sha256=f_4ZVFh8d9-6HPjrmy6nQ2cfpuY_nnovJYEZ1C4U7v4,27030
8
+ cycdp-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: scikit-build-core 0.11.6
3
+ Root-Is-Purelib: false
4
+ Tag: cp313-cp313-win_amd64
5
+