freesound-0.3.0: src/Sound/Freesound/Sound/Type.hs
{-# LANGUAGE CPP, OverloadedStrings #-}
module Sound.Freesound.Sound.Type where
import Control.Monad (mzero)
import Data.Aeson (FromJSON(..), Value(..), (.:), (.:?), decodeStrict)
import qualified Data.ByteString.Char8 as BS
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Network.HTTP.Types.QueryLike (QueryValueLike(..))
import Prelude hiding (id)
import Sound.Freesound.API (Resource, URI)
import Sound.Freesound.Comment (Comment)
import Sound.Freesound.List (List)
import Sound.Freesound.Pack.Type (Pack)
import Sound.Freesound.Time
-- import qualified Sound.Freesound.User.Type as User
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
newtype SoundId = SoundId { soundIdToInteger :: Integer }
deriving (Eq, Ord, Show)
instance FromJSON SoundId where
parseJSON (Number i) = return $ SoundId (truncate i)
parseJSON _ = mzero
--fromInt :: Int64 -> SoundId
--fromInt = SoundId
data FileType = WAV | AIFF | OGG | MP3 | FLAC
deriving (Eq, Show)
instance QueryValueLike FileType where
toQueryValue WAV = toQueryValue $ BS.pack "wav"
toQueryValue AIFF = toQueryValue $ BS.pack "aif"
toQueryValue OGG = toQueryValue $ BS.pack "ogg"
toQueryValue MP3 = toQueryValue $ BS.pack "mp3"
toQueryValue FLAC = toQueryValue $ BS.pack "flac"
instance FromJSON FileType where
parseJSON (String v) =
case v of
"wav" -> return WAV
"aiff" -> return AIFF
"aif" -> return AIFF
"ogg" -> return OGG
"mp3" -> return MP3
"flac" -> return FLAC
_ -> mzero
parseJSON _ = mzero
class Sound a where
-- | The sound’s unique identifier.
id :: a -> SoundId
-- | The name user gave to the sound.
name :: a -> Text
-- | An array of tags the user gave to the sound.
tags :: a -> [Text]
-- | The username of the uploader of the sound.
username :: a -> Text
-- | The license under which the sound is available to you.
license :: a -> License
data License =
Attribution
| AttributionNoncommercial
| CreativeCommons0
| License Text
deriving (Eq, Show)
instance FromJSON License where
parseJSON (String x) =
case x of
"Attribution" -> pure Attribution
"Attribution Noncommercial" -> pure AttributionNoncommercial
"Creative Commons 0" -> pure CreativeCommons0
u -> pure $ License u
parseJSON _ = fail "Invalid license"
data Previews = Previews {
preview_hq_mp3 :: URI -- ^ The URI for retrieving a high quality (~128kbps) mp3 preview of the sound.
, preview_lq_mp3 :: URI -- ^ The URI for retrieving a low quality (~64kbps) mp3 preview of the sound.
, preview_hq_ogg :: URI -- ^ The URI for retrieving a high quality (~192kbps) ogg preview of the sound.
, preview_lq_ogg :: URI -- ^ The URI for retrieving a low quality (~80kbps) ogg of the sound.
} deriving (Eq, Show)
instance FromJSON Previews where
parseJSON (Object v) =
Previews
<$> v .: "preview-hq-mp3"
<*> v .: "preview-lq-mp3"
<*> v .: "preview-hq-ogg"
<*> v .: "preview-lq-ogg"
parseJSON _ = fail "Couldn't parse Previews"
data Images = Images {
waveform_m :: URI -- ^ A visualization of the sounds waveform, png file (medium).
, waveform_l :: URI -- ^ A visualization of the sounds waveform, png file (large).
, spectral_m :: URI -- ^ A visualization of the sounds spectrum over time, jpeg file (medium).
, spectral_l :: URI -- ^ A visualization of the sounds spectrum over time, jpeg file (large).
} deriving (Eq, Show)
instance FromJSON Images where
parseJSON (Object v) =
Images
<$> v .: "waveform_m"
<*> v .: "waveform_l"
<*> v .: "spectral_m"
<*> v .: "spectral_l"
parseJSON _ = fail "Couldn't parse Images"
data Detail = Detail {
sound_id :: SoundId -- ^ The sound’s unique identifier.
, url :: URI -- ^ The URI for this sound on the Freesound website.
, sound_name :: Text -- ^ The name user gave to the sound.
, sound_tags :: [Text] -- ^ An array of tags the user gave to the sound.
, description :: Text -- ^ The description the user gave to the sound.
, geotag :: Maybe GeoTag -- ^ Latitude and longitude of the geotag (only for sounds that have been geotagged).
, created :: UTCTime -- ^ The date of when the sound was uploaded.
, sound_license :: License -- ^ The license under which the sound is available to you.
, fileType :: FileType -- ^ The type of sound (wav, aif, mp3, etc.).
, channels :: Int -- ^ The number of channels.
, filesize :: Integer -- ^ The size of the file in bytes.
, bitrate :: Int -- ^ The bit rate of the sound.
, bitdepth :: Int -- ^ The bit depth of the sound.
, duration :: Double -- ^ The duration of the sound in seconds.
, samplerate :: Int -- ^ The samplerate of the sound.
, sound_username :: Text -- ^ The username of the uploader of the sound.
, pack :: Maybe (Resource Pack) -- ^ If the sound is part of a pack, this URI points to that pack’s API resource.
, download :: URI -- ^ The URI for retrieving the original sound.
, bookmark :: URI -- ^ The URI for bookmarking the sound.
, previews :: Previews -- ^ Dictionary containing the URIs for mp3 and ogg versions of the sound. The dictionary includes the fields preview-hq-mp3 and preview-lq-mp3 (for ~128kbps quality and ~64kbps quality mp3 respectively), and preview-hq-ogg and preview-lq-ogg (for ~192kbps quality and ~80kbps quality ogg respectively).
, images :: Images -- ^ Dictionary including the URIs for spectrogram and waveform visualizations of the sound. The dinctionary includes the fields waveform_l and waveform_m (for large and medium waveform images respectively), and spectral_l and spectral_m (for large and medium spectrogram images respectively).
, numDownloads :: Integer -- ^ The number of times the sound was downloaded.
, avgRating :: Double -- ^ The average rating of the sound.
, numRatings :: Integer -- ^ The number of times the sound was rated.
, rate :: URI -- ^ The URI for rating the sound.
, comments :: Resource (List Comment) -- ^ The URI of a paginated list of the comments of the sound.
, numComments :: Integer -- ^ The number of comments.
, comment :: URI -- ^ The URI to comment the sound.
, similarSounds :: Resource (List Summary) -- ^ URI pointing to the similarity resource (to get a list of similar sounds).
-- , analysis :: Maybe
, analysisStats :: Resource () -- ^ URI pointing to the complete analysis results of the sound.
, analysisFrames :: Resource () -- ^ The URI for retrieving a JSON file with analysis information for each frame of the sound.
} deriving (Eq, Show)
instance FromJSON Detail where
parseJSON (Object v) =
Detail
<$> v .: "id"
<*> v .: "url"
<*> v .: "name"
<*> v .: "tags"
<*> v .: "description"
<*> v .:? "geotag"
<*> (toUTCTime <$> (v .: "created"))
<*> v .: "license"
<*> v .: "type"
<*> v .: "channels"
<*> v .: "filesize"
<*> v .: "bitrate"
<*> v .: "bitdepth"
<*> v .: "duration"
<*> v .: "samplerate"
<*> v .: "username"
<*> v .:? "pack"
<*> v .: "download"
<*> v .: "bookmark"
<*> v .: "previews"
<*> v .: "images"
<*> v .: "num_downloads"
<*> v .: "avg_rating"
<*> v .: "num_ratings"
<*> v .: "rate"
<*> v .: "comments"
<*> v .: "num_comments"
<*> v .: "comment"
<*> v .: "similar_sounds"
<*> v .: "analysis_stats"
<*> v .: "analysis_frames"
parseJSON _ = fail "Couldn't parse Sound"
instance Sound Detail where
id = sound_id
name = sound_name
tags = sound_tags
username = sound_username
license = sound_license
data Summary = Summary {
summary_id :: SoundId
, summary_name :: Text
, summary_tags :: [Text]
, summary_username :: Text
, summary_license :: License
} deriving (Eq, Show)
instance FromJSON Summary where
parseJSON (Object v) =
Summary
<$> v .: "id"
<*> v .: "name"
<*> v .: "tags"
<*> v .: "username"
<*> v .: "license"
parseJSON _ = fail "Couldn't parse Sound"
instance Sound Summary where
id = summary_id
name = summary_name
tags = summary_tags
username = summary_username
license = summary_license
-- | Coordinate
data GeoTag = GeoTag {
latitude :: Double
, longitude :: Double
} deriving (Eq, Show)
instance FromJSON GeoTag where
parseJSON (String s) = do
let coords = T.concat ["[", T.intercalate "," (T.splitOn " " s), "]"]
case decodeStrict (T.encodeUtf8 coords) of
Just [lat, lon] -> return $ GeoTag lat lon
_ -> fail "Couldn't parse GeoTag"
parseJSON _ = fail "Couldn't parse GeoTag"