defmodule DiffrhythmAi do @moduledoc """ Provides core functionality for interacting with the Diffrhythm.ai platform. This module offers utility functions for building API URLs and performing common tasks related to music generation and analysis. """ @base_url "https://diffrhythm.ai/api" @doc """ Builds a URL for the Diffrhythm.ai API, optionally adding query parameters. ## Examples iex> DiffrhythmAi.build_url("/music/generate", %{style: "jazz", duration: 60}) "https://diffrhythm.ai/api/music/generate?style=jazz&duration=60" iex> DiffrhythmAi.build_url("/music/analyze") "https://diffrhythm.ai/api/music/analyze" """ def build_url(path, params \\ %{}) do url = @base_url <> path if map_size(params) == 0 do url else query_string = params |> Enum.map(fn {key, value} -> "#{key}=#{value}" end) |> Enum.join("&") url <> "?" <> query_string end end @doc """ Generates a unique identifier for a music track. This function combines a timestamp with a random number to create a reasonably unique ID. ## Examples iex> String.length(DiffrhythmAi.generate_track_id()) 18 """ def generate_track_id do timestamp = System.os_time() random_number = :rand.uniform(1000) "track_#{timestamp}_#{random_number}" end @doc """ Normalizes a music style string to a consistent format. This function converts the style to lowercase and removes leading/trailing whitespace. ## Examples iex> DiffrhythmAi.normalize_style(" JaZz ") "jazz" iex> DiffrhythmAi.normalize_style("Classical") "classical" """ def normalize_style(style) when is_binary(style) do style |> String.downcase() |> String.trim() end @doc """ Calculates the estimated file size (in bytes) of a generated music track based on its duration and bitrate. ## Examples iex> DiffrhythmAi.estimate_file_size(60, 128) 960000 iex> DiffrhythmAi.estimate_file_size(120, 256) 4800000 """ def estimate_file_size(duration_seconds, bitrate_kbps) when is_integer(duration_seconds) and is_integer(bitrate_kbps) do (duration_seconds * bitrate_kbps * 1000) / 8 end @doc """ Validates a given duration in seconds to ensure it is within reasonable bounds (1-600 seconds). ## Examples iex> DiffrhythmAi.validate_duration(60) :ok iex> DiffrhythmAi.validate_duration(0) {:error, :invalid_duration} iex> DiffrhythmAi.validate_duration(700) {:error, :invalid_duration} """ def validate_duration(duration_seconds) when is_integer(duration_seconds) do if duration_seconds in 1..600 do :ok else {:error, :invalid_duration} end end end